Merge branch 'fix-flake8-issues'
This commit is contained in:
commit
c92760dca8
1
AUTHORS
1
AUTHORS
|
@ -9,6 +9,7 @@ Ahn Ki-Wook
|
|||
Alexander Johnson
|
||||
Alexei Kozlenok
|
||||
Anatoly Bubenkoff
|
||||
Andras Tim
|
||||
Andreas Zeidler
|
||||
Andrzej Ostrowski
|
||||
Andy Freeland
|
||||
|
|
|
@ -62,14 +62,16 @@ import sys
|
|||
import os
|
||||
from glob import glob
|
||||
|
||||
|
||||
class FastFilesCompleter:
|
||||
'Fast file completer class'
|
||||
|
||||
def __init__(self, directories=True):
|
||||
self.directories = directories
|
||||
|
||||
def __call__(self, prefix, **kwargs):
|
||||
"""only called on non option completions"""
|
||||
if os.path.sep in prefix[1:]: #
|
||||
if os.path.sep in prefix[1:]:
|
||||
prefix_dir = len(os.path.dirname(prefix) + os.path.sep)
|
||||
else:
|
||||
prefix_dir = 0
|
||||
|
@ -98,5 +100,6 @@ if os.environ.get('_ARGCOMPLETE'):
|
|||
def try_argcomplete(parser):
|
||||
argcomplete.autocomplete(parser)
|
||||
else:
|
||||
def try_argcomplete(parser): pass
|
||||
def try_argcomplete(parser):
|
||||
pass
|
||||
filescompleter = None
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
import types
|
||||
|
||||
|
||||
def format_exception_only(etype, value):
|
||||
"""Format the exception part of a traceback.
|
||||
|
||||
|
@ -30,7 +31,7 @@ def format_exception_only(etype, value):
|
|||
# would throw another exception and mask the original problem.
|
||||
if (isinstance(etype, BaseException) or
|
||||
isinstance(etype, types.InstanceType) or
|
||||
etype is None or type(etype) is str):
|
||||
etype is None or type(etype) is str):
|
||||
return [_format_final_exc_line(etype, value)]
|
||||
|
||||
stype = etype.__name__
|
||||
|
@ -62,6 +63,7 @@ def format_exception_only(etype, value):
|
|||
lines.append(_format_final_exc_line(stype, value))
|
||||
return lines
|
||||
|
||||
|
||||
def _format_final_exc_line(etype, value):
|
||||
"""Return a list of a single line -- normal case for format_exception_only"""
|
||||
valuestr = _some_str(value)
|
||||
|
@ -71,6 +73,7 @@ def _format_final_exc_line(etype, value):
|
|||
line = "%s: %s\n" % (etype, valuestr)
|
||||
return line
|
||||
|
||||
|
||||
def _some_str(value):
|
||||
try:
|
||||
return unicode(value)
|
||||
|
|
|
@ -18,6 +18,7 @@ else:
|
|||
|
||||
class Code(object):
|
||||
""" wrapper around Python code objects """
|
||||
|
||||
def __init__(self, rawcode):
|
||||
if not hasattr(rawcode, "co_filename"):
|
||||
rawcode = getrawcode(rawcode)
|
||||
|
@ -26,7 +27,7 @@ class Code(object):
|
|||
self.firstlineno = rawcode.co_firstlineno - 1
|
||||
self.name = rawcode.co_name
|
||||
except AttributeError:
|
||||
raise TypeError("not a code object: %r" %(rawcode,))
|
||||
raise TypeError("not a code object: %r" % (rawcode,))
|
||||
self.raw = rawcode
|
||||
|
||||
def __eq__(self, other):
|
||||
|
@ -82,6 +83,7 @@ class Code(object):
|
|||
argcount += raw.co_flags & CO_VARKEYWORDS
|
||||
return raw.co_varnames[:argcount]
|
||||
|
||||
|
||||
class Frame(object):
|
||||
"""Wrapper around a Python frame holding f_locals and f_globals
|
||||
in which expressions can be evaluated."""
|
||||
|
@ -119,7 +121,7 @@ class Frame(object):
|
|||
"""
|
||||
f_locals = self.f_locals.copy()
|
||||
f_locals.update(vars)
|
||||
py.builtin.exec_(code, self.f_globals, f_locals )
|
||||
py.builtin.exec_(code, self.f_globals, f_locals)
|
||||
|
||||
def repr(self, object):
|
||||
""" return a 'safe' (non-recursive, one-line) string repr for 'object'
|
||||
|
@ -143,6 +145,7 @@ class Frame(object):
|
|||
pass # this can occur when using Psyco
|
||||
return retval
|
||||
|
||||
|
||||
class TracebackEntry(object):
|
||||
""" a single entry in a traceback """
|
||||
|
||||
|
@ -168,7 +171,7 @@ class TracebackEntry(object):
|
|||
return self.lineno - self.frame.code.firstlineno
|
||||
|
||||
def __repr__(self):
|
||||
return "<TracebackEntry %s:%d>" %(self.frame.code.path, self.lineno+1)
|
||||
return "<TracebackEntry %s:%d>" % (self.frame.code.path, self.lineno + 1)
|
||||
|
||||
@property
|
||||
def statement(self):
|
||||
|
@ -249,17 +252,19 @@ class TracebackEntry(object):
|
|||
raise
|
||||
except:
|
||||
line = "???"
|
||||
return " File %r:%d in %s\n %s\n" %(fn, self.lineno+1, name, line)
|
||||
return " File %r:%d in %s\n %s\n" % (fn, self.lineno + 1, name, line)
|
||||
|
||||
def name(self):
|
||||
return self.frame.code.raw.co_name
|
||||
name = property(name, None, None, "co_name of underlaying code")
|
||||
|
||||
|
||||
class Traceback(list):
|
||||
""" Traceback objects encapsulate and offer higher level
|
||||
access to Traceback entries.
|
||||
"""
|
||||
Entry = TracebackEntry
|
||||
|
||||
def __init__(self, tb, excinfo=None):
|
||||
""" initialize from given python traceback object and ExceptionInfo """
|
||||
self._excinfo = excinfo
|
||||
|
@ -289,7 +294,7 @@ class Traceback(list):
|
|||
(excludepath is None or not hasattr(codepath, 'relto') or
|
||||
not codepath.relto(excludepath)) and
|
||||
(lineno is None or x.lineno == lineno) and
|
||||
(firstlineno is None or x.frame.code.firstlineno == firstlineno)):
|
||||
(firstlineno is None or x.frame.code.firstlineno == firstlineno)):
|
||||
return Traceback(x._rawentry, self._excinfo)
|
||||
return self
|
||||
|
||||
|
@ -315,7 +320,7 @@ class Traceback(list):
|
|||
""" return last non-hidden traceback entry that lead
|
||||
to the exception of a traceback.
|
||||
"""
|
||||
for i in range(-1, -len(self)-1, -1):
|
||||
for i in range(-1, -len(self) - 1, -1):
|
||||
entry = self[i]
|
||||
if not entry.ishidden():
|
||||
return entry
|
||||
|
@ -330,17 +335,17 @@ class Traceback(list):
|
|||
# id for the code.raw is needed to work around
|
||||
# the strange metaprogramming in the decorator lib from pypi
|
||||
# which generates code objects that have hash/value equality
|
||||
#XXX needs a test
|
||||
# XXX needs a test
|
||||
key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
|
||||
#print "checking for recursion at", key
|
||||
# print "checking for recursion at", key
|
||||
l = cache.setdefault(key, [])
|
||||
if l:
|
||||
f = entry.frame
|
||||
loc = f.f_locals
|
||||
for otherloc in l:
|
||||
if f.is_true(f.eval(co_equal,
|
||||
__recursioncache_locals_1=loc,
|
||||
__recursioncache_locals_2=otherloc)):
|
||||
__recursioncache_locals_1=loc,
|
||||
__recursioncache_locals_2=otherloc)):
|
||||
return i
|
||||
l.append(entry.frame.f_locals)
|
||||
return None
|
||||
|
@ -349,6 +354,7 @@ class Traceback(list):
|
|||
co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
|
||||
'?', 'eval')
|
||||
|
||||
|
||||
class ExceptionInfo(object):
|
||||
""" wraps sys.exc_info() objects and offers
|
||||
help for navigating the traceback.
|
||||
|
@ -405,10 +411,10 @@ class ExceptionInfo(object):
|
|||
exconly = self.exconly(tryshort=True)
|
||||
entry = self.traceback.getcrashentry()
|
||||
path, lineno = entry.frame.code.raw.co_filename, entry.lineno
|
||||
return ReprFileLocation(path, lineno+1, exconly)
|
||||
return ReprFileLocation(path, lineno + 1, exconly)
|
||||
|
||||
def getrepr(self, showlocals=False, style="long",
|
||||
abspath=False, tbfilter=True, funcargs=False):
|
||||
abspath=False, tbfilter=True, funcargs=False):
|
||||
""" return str()able representation of this exception info.
|
||||
showlocals: show locals per traceback entry
|
||||
style: long|short|no|native traceback style
|
||||
|
@ -425,7 +431,7 @@ class ExceptionInfo(object):
|
|||
)), self._getreprcrash())
|
||||
|
||||
fmt = FormattedExcinfo(showlocals=showlocals, style=style,
|
||||
abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
|
||||
abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
|
||||
return fmt.repr_excinfo(self)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -469,7 +475,7 @@ class FormattedExcinfo(object):
|
|||
def _getindent(self, source):
|
||||
# figure out indent for given source
|
||||
try:
|
||||
s = str(source.getstatement(len(source)-1))
|
||||
s = str(source.getstatement(len(source) - 1))
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except:
|
||||
|
@ -513,7 +519,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)
|
||||
|
@ -546,10 +552,10 @@ class FormattedExcinfo(object):
|
|||
# _repr() function, which is only reprlib.Repr in
|
||||
# disguise, so is very configurable.
|
||||
str_repr = self._saferepr(value)
|
||||
#if len(str_repr) < 70 or not isinstance(value,
|
||||
# if len(str_repr) < 70 or not isinstance(value,
|
||||
# (list, tuple, dict)):
|
||||
lines.append("%-10s = %s" %(name, str_repr))
|
||||
#else:
|
||||
lines.append("%-10s = %s" % (name, str_repr))
|
||||
# else:
|
||||
# self._line("%-10s =\\" % (name,))
|
||||
# # XXX
|
||||
# py.std.pprint.pprint(value, stream=self.excinfowriter)
|
||||
|
@ -575,14 +581,14 @@ class FormattedExcinfo(object):
|
|||
s = self.get_source(source, line_index, excinfo, short=short)
|
||||
lines.extend(s)
|
||||
if short:
|
||||
message = "in %s" %(entry.name)
|
||||
message = "in %s" % (entry.name)
|
||||
else:
|
||||
message = excinfo and excinfo.typename or ""
|
||||
path = self._makepath(entry.path)
|
||||
filelocrepr = ReprFileLocation(path, entry.lineno+1, message)
|
||||
filelocrepr = ReprFileLocation(path, entry.lineno + 1, message)
|
||||
localsrepr = None
|
||||
if not short:
|
||||
localsrepr = self.repr_locals(entry.locals)
|
||||
localsrepr = self.repr_locals(entry.locals)
|
||||
return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
|
||||
if excinfo:
|
||||
lines.extend(self.get_exconly(excinfo, indent=4))
|
||||
|
@ -645,7 +651,7 @@ class FormattedExcinfo(object):
|
|||
traceback = traceback[:recursionindex + 1]
|
||||
else:
|
||||
extraline = None
|
||||
|
||||
|
||||
return traceback, extraline
|
||||
|
||||
def repr_excinfo(self, excinfo):
|
||||
|
@ -699,7 +705,7 @@ class TerminalRepr(object):
|
|||
return io.getvalue().strip()
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s instance at %0x>" %(self.__class__, id(self))
|
||||
return "<%s instance at %0x>" % (self.__class__, id(self))
|
||||
|
||||
|
||||
class ExceptionRepr(TerminalRepr):
|
||||
|
@ -743,6 +749,7 @@ class ReprExceptionInfo(ExceptionRepr):
|
|||
self.reprtraceback.toterminal(tw)
|
||||
super(ReprExceptionInfo, self).toterminal(tw)
|
||||
|
||||
|
||||
class ReprTraceback(TerminalRepr):
|
||||
entrysep = "_ "
|
||||
|
||||
|
@ -758,7 +765,7 @@ class ReprTraceback(TerminalRepr):
|
|||
tw.line("")
|
||||
entry.toterminal(tw)
|
||||
if i < len(self.reprentries) - 1:
|
||||
next_entry = self.reprentries[i+1]
|
||||
next_entry = self.reprentries[i + 1]
|
||||
if entry.style == "long" or \
|
||||
entry.style == "short" and next_entry.style == "long":
|
||||
tw.sep(self.entrysep)
|
||||
|
@ -766,12 +773,14 @@ class ReprTraceback(TerminalRepr):
|
|||
if self.extraline:
|
||||
tw.line(self.extraline)
|
||||
|
||||
|
||||
class ReprTracebackNative(ReprTraceback):
|
||||
def __init__(self, tblines):
|
||||
self.style = "native"
|
||||
self.reprentries = [ReprEntryNative(tblines)]
|
||||
self.extraline = None
|
||||
|
||||
|
||||
class ReprEntryNative(TerminalRepr):
|
||||
style = "native"
|
||||
|
||||
|
@ -781,6 +790,7 @@ class ReprEntryNative(TerminalRepr):
|
|||
def toterminal(self, tw):
|
||||
tw.write("".join(self.lines))
|
||||
|
||||
|
||||
class ReprEntry(TerminalRepr):
|
||||
localssep = "_ "
|
||||
|
||||
|
@ -797,7 +807,7 @@ class ReprEntry(TerminalRepr):
|
|||
for line in self.lines:
|
||||
red = line.startswith("E ")
|
||||
tw.line(line, bold=True, red=red)
|
||||
#tw.line("")
|
||||
# tw.line("")
|
||||
return
|
||||
if self.reprfuncargs:
|
||||
self.reprfuncargs.toterminal(tw)
|
||||
|
@ -805,7 +815,7 @@ class ReprEntry(TerminalRepr):
|
|||
red = line.startswith("E ")
|
||||
tw.line(line, bold=True, red=red)
|
||||
if self.reprlocals:
|
||||
#tw.sep(self.localssep, "Locals")
|
||||
# tw.sep(self.localssep, "Locals")
|
||||
tw.line("")
|
||||
self.reprlocals.toterminal(tw)
|
||||
if self.reprfileloc:
|
||||
|
@ -818,6 +828,7 @@ class ReprEntry(TerminalRepr):
|
|||
self.reprlocals,
|
||||
self.reprfileloc)
|
||||
|
||||
|
||||
class ReprFileLocation(TerminalRepr):
|
||||
def __init__(self, path, lineno, message):
|
||||
self.path = str(path)
|
||||
|
@ -834,6 +845,7 @@ class ReprFileLocation(TerminalRepr):
|
|||
tw.write(self.path, bold=True, red=True)
|
||||
tw.line(":%s: %s" % (self.lineno, msg))
|
||||
|
||||
|
||||
class ReprLocals(TerminalRepr):
|
||||
def __init__(self, lines):
|
||||
self.lines = lines
|
||||
|
@ -842,6 +854,7 @@ class ReprLocals(TerminalRepr):
|
|||
for line in self.lines:
|
||||
tw.line(line)
|
||||
|
||||
|
||||
class ReprFuncArgs(TerminalRepr):
|
||||
def __init__(self, args):
|
||||
self.args = args
|
||||
|
@ -850,11 +863,11 @@ class ReprFuncArgs(TerminalRepr):
|
|||
if self.args:
|
||||
linesofar = ""
|
||||
for name, value in self.args:
|
||||
ns = "%s = %s" %(name, value)
|
||||
ns = "%s = %s" % (name, value)
|
||||
if len(ns) + len(linesofar) + 2 > tw.fullwidth:
|
||||
if linesofar:
|
||||
tw.line(linesofar)
|
||||
linesofar = ns
|
||||
linesofar = ns
|
||||
else:
|
||||
if linesofar:
|
||||
linesofar += ", " + ns
|
||||
|
|
|
@ -2,7 +2,8 @@ from __future__ import absolute_import, division, generators, print_function
|
|||
|
||||
from bisect import bisect_right
|
||||
import sys
|
||||
import inspect, tokenize
|
||||
import inspect
|
||||
import tokenize
|
||||
import py
|
||||
cpy_compile = compile
|
||||
|
||||
|
@ -19,6 +20,7 @@ class Source(object):
|
|||
possibly deindenting it.
|
||||
"""
|
||||
_compilecounter = 0
|
||||
|
||||
def __init__(self, *parts, **kwargs):
|
||||
self.lines = lines = []
|
||||
de = kwargs.get('deindent', True)
|
||||
|
@ -73,7 +75,7 @@ class Source(object):
|
|||
start, end = 0, len(self)
|
||||
while start < end and not self.lines[start].strip():
|
||||
start += 1
|
||||
while end > start and not self.lines[end-1].strip():
|
||||
while end > start and not self.lines[end - 1].strip():
|
||||
end -= 1
|
||||
source = Source()
|
||||
source.lines[:] = self.lines[start:end]
|
||||
|
@ -86,8 +88,8 @@ class Source(object):
|
|||
before = Source(before)
|
||||
after = Source(after)
|
||||
newsource = Source()
|
||||
lines = [ (indent + line) for line in self.lines]
|
||||
newsource.lines = before.lines + lines + after.lines
|
||||
lines = [(indent + line) for line in self.lines]
|
||||
newsource.lines = before.lines + lines + after.lines
|
||||
return newsource
|
||||
|
||||
def indent(self, indent=' ' * 4):
|
||||
|
@ -95,7 +97,7 @@ class Source(object):
|
|||
all lines indented by the given indent-string.
|
||||
"""
|
||||
newsource = Source()
|
||||
newsource.lines = [(indent+line) for line in self.lines]
|
||||
newsource.lines = [(indent + line) for line in self.lines]
|
||||
return newsource
|
||||
|
||||
def getstatement(self, lineno, assertion=False):
|
||||
|
@ -134,7 +136,8 @@ class Source(object):
|
|||
try:
|
||||
import parser
|
||||
except ImportError:
|
||||
syntax_checker = lambda x: compile(x, 'asd', 'exec')
|
||||
def syntax_checker(x):
|
||||
return compile(x, 'asd', 'exec')
|
||||
else:
|
||||
syntax_checker = parser.suite
|
||||
|
||||
|
@ -143,8 +146,8 @@ class Source(object):
|
|||
else:
|
||||
source = str(self)
|
||||
try:
|
||||
#compile(source+'\n', "x", "exec")
|
||||
syntax_checker(source+'\n')
|
||||
# compile(source+'\n', "x", "exec")
|
||||
syntax_checker(source + '\n')
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except Exception:
|
||||
|
@ -164,8 +167,8 @@ class Source(object):
|
|||
"""
|
||||
if not filename or py.path.local(filename).check(file=0):
|
||||
if _genframe is None:
|
||||
_genframe = sys._getframe(1) # the caller
|
||||
fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno
|
||||
_genframe = sys._getframe(1) # the caller
|
||||
fn, lineno = _genframe.f_code.co_filename, _genframe.f_lineno
|
||||
base = "<%d-codegen " % self._compilecounter
|
||||
self.__class__._compilecounter += 1
|
||||
if not filename:
|
||||
|
@ -180,7 +183,7 @@ class Source(object):
|
|||
# re-represent syntax errors from parsing python strings
|
||||
msglines = self.lines[:ex.lineno]
|
||||
if ex.offset:
|
||||
msglines.append(" "*ex.offset + '^')
|
||||
msglines.append(" " * ex.offset + '^')
|
||||
msglines.append("(code was compiled probably from here: %s)" % filename)
|
||||
newex = SyntaxError('\n'.join(msglines))
|
||||
newex.offset = ex.offset
|
||||
|
@ -198,8 +201,8 @@ class Source(object):
|
|||
# public API shortcut functions
|
||||
#
|
||||
|
||||
def compile_(source, filename=None, mode='exec', flags=
|
||||
generators.compiler_flag, dont_inherit=0):
|
||||
|
||||
def compile_(source, filename=None, mode='exec', flags=generators.compiler_flag, dont_inherit=0):
|
||||
""" compile the given source to a raw code object,
|
||||
and maintain an internal cache which allows later
|
||||
retrieval of the source code for the code object
|
||||
|
@ -208,7 +211,7 @@ def compile_(source, filename=None, mode='exec', flags=
|
|||
if _ast is not None and isinstance(source, _ast.AST):
|
||||
# XXX should Source support having AST?
|
||||
return cpy_compile(source, filename, mode, flags, dont_inherit)
|
||||
_genframe = sys._getframe(1) # the caller
|
||||
_genframe = sys._getframe(1) # the caller
|
||||
s = Source(source)
|
||||
co = s.compile(filename, mode, flags, _genframe=_genframe)
|
||||
return co
|
||||
|
@ -245,6 +248,7 @@ def getfslineno(obj):
|
|||
# helper functions
|
||||
#
|
||||
|
||||
|
||||
def findsource(obj):
|
||||
try:
|
||||
sourcelines, lineno = py.std.inspect.findsource(obj)
|
||||
|
@ -274,7 +278,7 @@ def deindent(lines, offset=None):
|
|||
line = line.expandtabs()
|
||||
s = line.lstrip()
|
||||
if s:
|
||||
offset = len(line)-len(s)
|
||||
offset = len(line) - len(s)
|
||||
break
|
||||
else:
|
||||
offset = 0
|
||||
|
@ -293,11 +297,11 @@ def deindent(lines, offset=None):
|
|||
try:
|
||||
for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
|
||||
if sline > len(lines):
|
||||
break # End of input reached
|
||||
break # End of input reached
|
||||
if sline > len(newlines):
|
||||
line = lines[sline - 1].expandtabs()
|
||||
if line.lstrip() and line[:offset].isspace():
|
||||
line = line[offset:] # Deindent
|
||||
line = line[offset:] # Deindent
|
||||
newlines.append(line)
|
||||
|
||||
for i in range(sline, eline):
|
||||
|
@ -337,7 +341,7 @@ def get_statement_startend2(lineno, node):
|
|||
def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
|
||||
if astnode is None:
|
||||
content = str(source)
|
||||
if sys.version_info < (2,7):
|
||||
if sys.version_info < (2, 7):
|
||||
content += "\n"
|
||||
try:
|
||||
astnode = compile(content, "source", "exec", 1024) # 1024 for AST
|
||||
|
@ -393,7 +397,7 @@ def getstatementrange_old(lineno, source, assertion=False):
|
|||
raise IndexError("likely a subclass")
|
||||
if "assert" not in line and "raise" not in line:
|
||||
continue
|
||||
trylines = source.lines[start:lineno+1]
|
||||
trylines = source.lines[start:lineno + 1]
|
||||
# quick hack to prepare parsing an indented line with
|
||||
# compile_command() (which errors on "return" outside defs)
|
||||
trylines.insert(0, 'def xxx():')
|
||||
|
@ -405,10 +409,8 @@ def getstatementrange_old(lineno, source, assertion=False):
|
|||
continue
|
||||
|
||||
# 2. find the end of the statement
|
||||
for end in range(lineno+1, len(source)+1):
|
||||
for end in range(lineno + 1, len(source) + 1):
|
||||
trysource = source[start:end]
|
||||
if trysource.isparseable():
|
||||
return start, end
|
||||
raise SyntaxError("no valid source range around line %d " % (lineno,))
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ def pytest_addoption(parser):
|
|||
expression information.""")
|
||||
|
||||
|
||||
|
||||
def register_assert_rewrite(*names):
|
||||
"""Register one or more module names to be rewritten on import.
|
||||
|
||||
|
|
|
@ -36,10 +36,11 @@ PYC_TAIL = "." + PYTEST_TAG + PYC_EXT
|
|||
REWRITE_NEWLINES = sys.version_info[:2] != (2, 7) and sys.version_info < (3, 2)
|
||||
ASCII_IS_DEFAULT_ENCODING = sys.version_info[0] < 3
|
||||
|
||||
if sys.version_info >= (3,5):
|
||||
if sys.version_info >= (3, 5):
|
||||
ast_Call = ast.Call
|
||||
else:
|
||||
ast_Call = lambda a,b,c: ast.Call(a, b, c, None, None)
|
||||
def ast_Call(a, b, c):
|
||||
return ast.Call(a, b, c, None, None)
|
||||
|
||||
|
||||
class AssertionRewritingHook(object):
|
||||
|
@ -215,8 +216,6 @@ class AssertionRewritingHook(object):
|
|||
raise
|
||||
return sys.modules[name]
|
||||
|
||||
|
||||
|
||||
def is_package(self, name):
|
||||
try:
|
||||
fd, fn, desc = imp.find_module(name)
|
||||
|
@ -261,7 +260,7 @@ def _write_pyc(state, co, source_stat, pyc):
|
|||
fp = open(pyc, "wb")
|
||||
except IOError:
|
||||
err = sys.exc_info()[1].errno
|
||||
state.trace("error writing pyc file at %s: errno=%s" %(pyc, err))
|
||||
state.trace("error writing pyc file at %s: errno=%s" % (pyc, err))
|
||||
# we ignore any failure to write the cache file
|
||||
# there are many reasons, permission-denied, __pycache__ being a
|
||||
# file etc.
|
||||
|
@ -283,6 +282,7 @@ N = "\n".encode("utf-8")
|
|||
cookie_re = re.compile(r"^[ \t\f]*#.*coding[:=][ \t]*[-\w.]+")
|
||||
BOM_UTF8 = '\xef\xbb\xbf'
|
||||
|
||||
|
||||
def _rewrite_test(config, fn):
|
||||
"""Try to read and rewrite *fn* and return the code object."""
|
||||
state = config._assertstate
|
||||
|
@ -307,7 +307,7 @@ def _rewrite_test(config, fn):
|
|||
end2 = source.find("\n", end1 + 1)
|
||||
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):
|
||||
cookie_re.match(source[end1 + 1:end2]) is None):
|
||||
if hasattr(state, "_indecode"):
|
||||
# encodings imported us again, so don't rewrite.
|
||||
return None, None
|
||||
|
@ -340,6 +340,7 @@ def _rewrite_test(config, fn):
|
|||
return None, None
|
||||
return stat, co
|
||||
|
||||
|
||||
def _make_rewritten_pyc(state, source_stat, pyc, co):
|
||||
"""Try to dump rewritten code to *pyc*."""
|
||||
if sys.platform.startswith("win"):
|
||||
|
@ -353,6 +354,7 @@ def _make_rewritten_pyc(state, source_stat, pyc, co):
|
|||
if _write_pyc(state, co, source_stat, proc_pyc):
|
||||
os.rename(proc_pyc, pyc)
|
||||
|
||||
|
||||
def _read_pyc(source, pyc, trace=lambda x: None):
|
||||
"""Possibly read a pytest pyc containing rewritten code.
|
||||
|
||||
|
@ -410,7 +412,8 @@ def _saferepr(obj):
|
|||
return repr.replace(t("\n"), t("\\n"))
|
||||
|
||||
|
||||
from _pytest.assertion.util import format_explanation as _format_explanation # noqa
|
||||
from _pytest.assertion.util import format_explanation as _format_explanation # noqa
|
||||
|
||||
|
||||
def _format_assertmsg(obj):
|
||||
"""Format the custom assertion message given.
|
||||
|
@ -439,9 +442,11 @@ def _format_assertmsg(obj):
|
|||
s = s.replace(t("\\n"), t("\n~"))
|
||||
return s
|
||||
|
||||
|
||||
def _should_repr_global_name(obj):
|
||||
return not hasattr(obj, "__name__") and not py.builtin.callable(obj)
|
||||
|
||||
|
||||
def _format_boolop(explanations, is_or):
|
||||
explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")"
|
||||
if py.builtin._istext(explanation):
|
||||
|
@ -450,6 +455,7 @@ def _format_boolop(explanations, is_or):
|
|||
t = py.builtin.bytes
|
||||
return explanation.replace(t('%'), t('%%'))
|
||||
|
||||
|
||||
def _call_reprcompare(ops, results, expls, each_obj):
|
||||
for i, res, expl in zip(range(len(ops)), results, expls):
|
||||
try:
|
||||
|
@ -483,7 +489,7 @@ binop_map = {
|
|||
ast.Mult: "*",
|
||||
ast.Div: "/",
|
||||
ast.FloorDiv: "//",
|
||||
ast.Mod: "%%", # escaped for string formatting
|
||||
ast.Mod: "%%", # escaped for string formatting
|
||||
ast.Eq: "==",
|
||||
ast.NotEq: "!=",
|
||||
ast.Lt: "<",
|
||||
|
@ -723,7 +729,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
if isinstance(assert_.test, ast.Tuple) and self.config is not None:
|
||||
fslocation = (self.module_path, assert_.lineno)
|
||||
self.config.warn('R1', 'assertion is always true, perhaps '
|
||||
'remove parentheses?', fslocation=fslocation)
|
||||
'remove parentheses?', fslocation=fslocation)
|
||||
self.statements = []
|
||||
self.variables = []
|
||||
self.variable_counter = itertools.count()
|
||||
|
@ -787,7 +793,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
if i:
|
||||
fail_inner = []
|
||||
# cond is set in a prior loop iteration below
|
||||
self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa
|
||||
self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa
|
||||
self.on_failure = fail_inner
|
||||
self.push_format_context()
|
||||
res, expl = self.visit(v)
|
||||
|
@ -839,7 +845,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
new_kwargs.append(ast.keyword(keyword.arg, res))
|
||||
if keyword.arg:
|
||||
arg_expls.append(keyword.arg + "=" + expl)
|
||||
else: ## **args have `arg` keywords with an .arg of None
|
||||
else: # **args have `arg` keywords with an .arg of None
|
||||
arg_expls.append("**" + expl)
|
||||
|
||||
expl = "%s(%s)" % (func_expl, ', '.join(arg_expls))
|
||||
|
@ -893,7 +899,6 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
else:
|
||||
visit_Call = visit_Call_legacy
|
||||
|
||||
|
||||
def visit_Attribute(self, attr):
|
||||
if not isinstance(attr.ctx, ast.Load):
|
||||
return self.generic_visit(attr)
|
||||
|
|
|
@ -82,7 +82,7 @@ def _format_lines(lines):
|
|||
stack.append(len(result))
|
||||
stackcnt[-1] += 1
|
||||
stackcnt.append(0)
|
||||
result.append(u(' +') + u(' ')*(len(stack)-1) + s + line[1:])
|
||||
result.append(u(' +') + u(' ') * (len(stack) - 1) + s + line[1:])
|
||||
elif line.startswith('}'):
|
||||
stack.pop()
|
||||
stackcnt.pop()
|
||||
|
@ -91,7 +91,7 @@ def _format_lines(lines):
|
|||
assert line[0] in ['~', '>']
|
||||
stack[-1] += 1
|
||||
indent = len(stack) if line.startswith('~') else len(stack) - 1
|
||||
result.append(u(' ')*indent + line[1:])
|
||||
result.append(u(' ') * indent + line[1:])
|
||||
assert len(stack) == 1
|
||||
return result
|
||||
|
||||
|
@ -106,16 +106,22 @@ except NameError:
|
|||
def assertrepr_compare(config, op, left, right):
|
||||
"""Return specialised explanations for some operators/operands"""
|
||||
width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
|
||||
left_repr = py.io.saferepr(left, maxsize=int(width//2))
|
||||
right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
|
||||
left_repr = py.io.saferepr(left, maxsize=int(width // 2))
|
||||
right_repr = py.io.saferepr(right, maxsize=width - len(left_repr))
|
||||
|
||||
summary = u('%s %s %s') % (ecu(left_repr), op, ecu(right_repr))
|
||||
|
||||
issequence = lambda x: (isinstance(x, (list, tuple, Sequence)) and
|
||||
not isinstance(x, basestring))
|
||||
istext = lambda x: isinstance(x, basestring)
|
||||
isdict = lambda x: isinstance(x, dict)
|
||||
isset = lambda x: isinstance(x, (set, frozenset))
|
||||
def issequence(x):
|
||||
return (isinstance(x, (list, tuple, Sequence)) and not isinstance(x, basestring))
|
||||
|
||||
def istext(x):
|
||||
return isinstance(x, basestring)
|
||||
|
||||
def isdict(x):
|
||||
return isinstance(x, dict)
|
||||
|
||||
def isset(x):
|
||||
return isinstance(x, (set, frozenset))
|
||||
|
||||
def isiterable(obj):
|
||||
try:
|
||||
|
@ -285,7 +291,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)]
|
||||
|
|
|
@ -89,6 +89,7 @@ class Cache(object):
|
|||
|
||||
class LFPlugin:
|
||||
""" Plugin which implements the --lf (run last-failing) option """
|
||||
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
active_keys = 'lf', 'failedfirst'
|
||||
|
@ -179,7 +180,6 @@ def pytest_cmdline_main(config):
|
|||
return wrap_session(config, cacheshow)
|
||||
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_configure(config):
|
||||
config.cache = Cache(config)
|
||||
|
@ -224,7 +224,7 @@ def cacheshow(config, session):
|
|||
val = config.cache.get(key, dummy)
|
||||
if val is dummy:
|
||||
tw.line("%s contains unreadable content, "
|
||||
"will be ignored" % key)
|
||||
"will be ignored" % key)
|
||||
else:
|
||||
tw.line("%s contains:" % key)
|
||||
stream = py.io.TextIO()
|
||||
|
@ -236,7 +236,7 @@ def cacheshow(config, session):
|
|||
if ddir.isdir() and ddir.listdir():
|
||||
tw.sep("-", "cache directories")
|
||||
for p in sorted(basedir.join("d").visit()):
|
||||
#if p.check(dir=1):
|
||||
# if p.check(dir=1):
|
||||
# print("%s/" % p.relto(basedir))
|
||||
if p.isfile():
|
||||
key = p.relto(basedir)
|
||||
|
|
|
@ -134,7 +134,7 @@ class CaptureManager:
|
|||
self.resumecapture()
|
||||
self.activate_funcargs(item)
|
||||
yield
|
||||
#self.deactivate_funcargs() called from suspendcapture()
|
||||
# self.deactivate_funcargs() called from suspendcapture()
|
||||
self.suspendcapture_item(item, "call")
|
||||
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
|
@ -171,6 +171,7 @@ def capsys(request):
|
|||
request.node._capfuncarg = c = CaptureFixture(SysCapture, request)
|
||||
return c
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def capfd(request):
|
||||
"""Enable capturing of writes to file descriptors 1 and 2 and make
|
||||
|
@ -238,6 +239,7 @@ def safe_text_dupfile(f, mode, default_encoding="UTF8"):
|
|||
|
||||
class EncodedFile(object):
|
||||
errors = "strict" # possibly needed by py3 code (issue555)
|
||||
|
||||
def __init__(self, buffer, encoding):
|
||||
self.buffer = buffer
|
||||
self.encoding = encoding
|
||||
|
@ -318,9 +320,11 @@ class MultiCapture(object):
|
|||
return (self.out.snap() if self.out is not None else "",
|
||||
self.err.snap() if self.err is not None else "")
|
||||
|
||||
|
||||
class NoCapture:
|
||||
__init__ = start = done = suspend = resume = lambda *args: None
|
||||
|
||||
|
||||
class FDCapture:
|
||||
""" Capture IO to/from a given os-level filedescriptor. """
|
||||
|
||||
|
@ -393,7 +397,7 @@ class FDCapture:
|
|||
def writeorg(self, data):
|
||||
""" write to original file descriptor. """
|
||||
if py.builtin._istext(data):
|
||||
data = data.encode("utf8") # XXX use encoding of original stream
|
||||
data = data.encode("utf8") # XXX use encoding of original stream
|
||||
os.write(self.targetfd_save, data)
|
||||
|
||||
|
||||
|
@ -463,7 +467,7 @@ class DontReadFromInput:
|
|||
|
||||
@property
|
||||
def buffer(self):
|
||||
if sys.version_info >= (3,0):
|
||||
if sys.version_info >= (3, 0):
|
||||
return self
|
||||
else:
|
||||
raise AttributeError('redirected stdin has no attribute buffer')
|
||||
|
|
|
@ -10,8 +10,7 @@ import functools
|
|||
|
||||
import py
|
||||
|
||||
import _pytest
|
||||
|
||||
import _pytest
|
||||
|
||||
|
||||
try:
|
||||
|
@ -59,7 +58,7 @@ def iscoroutinefunction(func):
|
|||
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)))
|
||||
(hasattr(inspect, 'iscoroutinefunction') and inspect.iscoroutinefunction(func)))
|
||||
|
||||
|
||||
def getlocation(function, curdir):
|
||||
|
@ -68,7 +67,7 @@ def getlocation(function, curdir):
|
|||
lineno = py.builtin._getcode(function).co_firstlineno
|
||||
if fn.relto(curdir):
|
||||
fn = fn.relto(curdir)
|
||||
return "%s:%d" %(fn, lineno+1)
|
||||
return "%s:%d" % (fn, lineno + 1)
|
||||
|
||||
|
||||
def num_mock_patch_args(function):
|
||||
|
@ -79,13 +78,13 @@ def num_mock_patch_args(function):
|
|||
mock = sys.modules.get("mock", sys.modules.get("unittest.mock", None))
|
||||
if mock is not None:
|
||||
return len([p for p in patchings
|
||||
if not p.attribute_name and p.new is mock.DEFAULT])
|
||||
if not p.attribute_name and p.new is mock.DEFAULT])
|
||||
return len(patchings)
|
||||
|
||||
|
||||
def getfuncargnames(function, startindex=None):
|
||||
# XXX merge with main.py's varnames
|
||||
#assert not isclass(function)
|
||||
# assert not isclass(function)
|
||||
realfunction = function
|
||||
while hasattr(realfunction, "__wrapped__"):
|
||||
realfunction = realfunction.__wrapped__
|
||||
|
@ -111,8 +110,7 @@ def getfuncargnames(function, startindex=None):
|
|||
return tuple(argnames[startindex:])
|
||||
|
||||
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
def isclass(object):
|
||||
""" Return true if the object is a class. Overrides inspect.isclass for
|
||||
python 2.6 because it will return True for objects which always return
|
||||
|
@ -297,6 +295,7 @@ else:
|
|||
def getvalue(self):
|
||||
return self.buffer.getvalue().decode('UTF-8')
|
||||
|
||||
|
||||
class FuncargnamesCompatAttr(object):
|
||||
""" helper class so that Metafunc, Function and FixtureRequest
|
||||
don't need to each define the "funcargnames" compatibility attribute.
|
||||
|
|
|
@ -60,9 +60,10 @@ def main(args=None, plugins=None):
|
|||
config._ensure_unconfigure()
|
||||
except UsageError as e:
|
||||
for msg in e.args:
|
||||
sys.stderr.write("ERROR: %s\n" %(msg,))
|
||||
sys.stderr.write("ERROR: %s\n" % (msg,))
|
||||
return 4
|
||||
|
||||
|
||||
class cmdline: # compatibility namespace
|
||||
main = staticmethod(main)
|
||||
|
||||
|
@ -102,10 +103,10 @@ def directory_arg(path, optname):
|
|||
_preinit = []
|
||||
|
||||
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").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").split()
|
||||
|
||||
|
||||
builtin_plugins = set(default_plugins)
|
||||
|
@ -116,6 +117,7 @@ def _preloadplugins():
|
|||
assert not _preinit
|
||||
_preinit.append(get_config())
|
||||
|
||||
|
||||
def get_config():
|
||||
if _preinit:
|
||||
return _preinit.pop(0)
|
||||
|
@ -126,6 +128,7 @@ def get_config():
|
|||
pluginmanager.import_plugin(spec)
|
||||
return config
|
||||
|
||||
|
||||
def get_plugin_manager():
|
||||
"""
|
||||
Obtain a new instance of the
|
||||
|
@ -137,6 +140,7 @@ def get_plugin_manager():
|
|||
"""
|
||||
return get_config().pluginmanager
|
||||
|
||||
|
||||
def _prepareconfig(args=None, plugins=None):
|
||||
warning = None
|
||||
if args is None:
|
||||
|
@ -161,7 +165,7 @@ def _prepareconfig(args=None, plugins=None):
|
|||
if warning:
|
||||
config.warn('C1', warning)
|
||||
return pluginmanager.hook.pytest_cmdline_parse(
|
||||
pluginmanager=pluginmanager, args=args)
|
||||
pluginmanager=pluginmanager, args=args)
|
||||
except BaseException:
|
||||
config._ensure_unconfigure()
|
||||
raise
|
||||
|
@ -176,6 +180,7 @@ class PytestPluginManager(PluginManager):
|
|||
``pytest_plugins`` global variables found in plugins being loaded;
|
||||
* ``conftest.py`` loading during start-up;
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(PytestPluginManager, self).__init__("pytest", implprefix="pytest_")
|
||||
self._conftest_plugins = set()
|
||||
|
@ -206,7 +211,8 @@ class PytestPluginManager(PluginManager):
|
|||
"""
|
||||
.. deprecated:: 2.8
|
||||
|
||||
Use :py:meth:`pluggy.PluginManager.add_hookspecs <_pytest.vendored_packages.pluggy.PluginManager.add_hookspecs>` instead.
|
||||
Use :py:meth:`pluggy.PluginManager.add_hookspecs <_pytest.vendored_packages.pluggy.PluginManager.add_hookspecs>`
|
||||
instead.
|
||||
"""
|
||||
warning = dict(code="I2",
|
||||
fslocation=_pytest._code.getfslineno(sys._getframe(1)),
|
||||
|
@ -235,7 +241,7 @@ class PytestPluginManager(PluginManager):
|
|||
|
||||
def parse_hookspec_opts(self, module_or_class, name):
|
||||
opts = super(PytestPluginManager, self).parse_hookspec_opts(
|
||||
module_or_class, name)
|
||||
module_or_class, name)
|
||||
if opts is None:
|
||||
method = getattr(module_or_class, name)
|
||||
if name.startswith("pytest_"):
|
||||
|
@ -258,7 +264,7 @@ class PytestPluginManager(PluginManager):
|
|||
ret = super(PytestPluginManager, self).register(plugin, name)
|
||||
if ret:
|
||||
self.hook.pytest_plugin_registered.call_historic(
|
||||
kwargs=dict(plugin=plugin, manager=self))
|
||||
kwargs=dict(plugin=plugin, manager=self))
|
||||
|
||||
if isinstance(plugin, types.ModuleType):
|
||||
self.consider_module(plugin)
|
||||
|
@ -276,11 +282,11 @@ class PytestPluginManager(PluginManager):
|
|||
# XXX now that the pluginmanager exposes hookimpl(tryfirst...)
|
||||
# we should remove tryfirst/trylast as markers
|
||||
config.addinivalue_line("markers",
|
||||
"tryfirst: mark a hook implementation function such that the "
|
||||
"plugin machinery will try to call it first/as early as possible.")
|
||||
"tryfirst: mark a hook implementation function such that the "
|
||||
"plugin machinery will try to call it first/as early as possible.")
|
||||
config.addinivalue_line("markers",
|
||||
"trylast: mark a hook implementation function such that the "
|
||||
"plugin machinery will try to call it last/as late as possible.")
|
||||
"trylast: mark a hook implementation function such that the "
|
||||
"plugin machinery will try to call it last/as late as possible.")
|
||||
|
||||
def _warn(self, message):
|
||||
kwargs = message if isinstance(message, dict) else {
|
||||
|
@ -304,7 +310,7 @@ class PytestPluginManager(PluginManager):
|
|||
"""
|
||||
current = py.path.local()
|
||||
self._confcutdir = current.join(namespace.confcutdir, abs=True) \
|
||||
if namespace.confcutdir else None
|
||||
if namespace.confcutdir else None
|
||||
self._noconftest = namespace.noconftest
|
||||
testpaths = namespace.file_or_dir
|
||||
foundanchor = False
|
||||
|
@ -315,7 +321,7 @@ class PytestPluginManager(PluginManager):
|
|||
if i != -1:
|
||||
path = path[:i]
|
||||
anchor = current.join(path, abs=1)
|
||||
if exists(anchor): # we found some file object
|
||||
if exists(anchor): # we found some file object
|
||||
self._try_load_conftest(anchor)
|
||||
foundanchor = True
|
||||
if not foundanchor:
|
||||
|
@ -382,7 +388,7 @@ class PytestPluginManager(PluginManager):
|
|||
if path and path.relto(dirpath) or path == dirpath:
|
||||
assert mod not in mods
|
||||
mods.append(mod)
|
||||
self.trace("loaded conftestmodule %r" %(mod))
|
||||
self.trace("loaded conftestmodule %r" % (mod))
|
||||
self.consider_conftest(mod)
|
||||
return mod
|
||||
|
||||
|
@ -392,7 +398,7 @@ class PytestPluginManager(PluginManager):
|
|||
#
|
||||
|
||||
def consider_preparse(self, args):
|
||||
for opt1,opt2 in zip(args, args[1:]):
|
||||
for opt1, opt2 in zip(args, args[1:]):
|
||||
if opt1 == "-p":
|
||||
self.consider_pluginarg(opt2)
|
||||
|
||||
|
@ -446,7 +452,7 @@ class PytestPluginManager(PluginManager):
|
|||
import pytest
|
||||
if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception):
|
||||
raise
|
||||
self._warn("skipped plugin %r: %s" %((modname, e.msg)))
|
||||
self._warn("skipped plugin %r: %s" % ((modname, e.msg)))
|
||||
else:
|
||||
mod = sys.modules[importspec]
|
||||
self.register(mod, modname)
|
||||
|
@ -511,7 +517,7 @@ class Parser:
|
|||
for i, grp in enumerate(self._groups):
|
||||
if grp.name == after:
|
||||
break
|
||||
self._groups.insert(i+1, group)
|
||||
self._groups.insert(i + 1, group)
|
||||
return group
|
||||
|
||||
def addoption(self, *opts, **attrs):
|
||||
|
@ -549,7 +555,7 @@ class Parser:
|
|||
a = option.attrs()
|
||||
arggroup.add_argument(*n, **a)
|
||||
# bash like autocompletion for dirs (appending '/')
|
||||
optparser.add_argument(FILE_OR_DIR, nargs='*').completer=filescompleter
|
||||
optparser.add_argument(FILE_OR_DIR, nargs='*').completer = filescompleter
|
||||
return optparser
|
||||
|
||||
def parse_setoption(self, args, option, namespace=None):
|
||||
|
@ -693,7 +699,7 @@ class Argument:
|
|||
if self._attrs.get('help'):
|
||||
a = self._attrs['help']
|
||||
a = a.replace('%default', '%(default)s')
|
||||
#a = a.replace('%prog', '%(prog)s')
|
||||
# a = a.replace('%prog', '%(prog)s')
|
||||
self._attrs['help'] = a
|
||||
return self._attrs
|
||||
|
||||
|
@ -777,7 +783,7 @@ class MyOptionParser(argparse.ArgumentParser):
|
|||
extra_info = {}
|
||||
self._parser = parser
|
||||
argparse.ArgumentParser.__init__(self, usage=parser._usage,
|
||||
add_help=False, formatter_class=DropShorterLongHelpFormatter)
|
||||
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
|
||||
|
@ -805,9 +811,10 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
|||
- 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
|
||||
if orgstr and orgstr[0] != '-': # only optional arguments
|
||||
return orgstr
|
||||
res = getattr(action, '_formatted_action_invocation', None)
|
||||
if res:
|
||||
|
@ -818,7 +825,7 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
|||
action._formatted_action_invocation = orgstr
|
||||
return orgstr
|
||||
return_list = []
|
||||
option_map = getattr(action, 'map_long_option', {})
|
||||
option_map = getattr(action, 'map_long_option', {})
|
||||
if option_map is None:
|
||||
option_map = {}
|
||||
short_long = {}
|
||||
|
@ -836,7 +843,7 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
|||
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: #
|
||||
for option in options:
|
||||
if len(option) == 2 or option[2] == ' ':
|
||||
return_list.append(option)
|
||||
if option[2:] == short_long.get(option.replace('-', '')):
|
||||
|
@ -845,22 +852,26 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
|||
return action._formatted_action_invocation
|
||||
|
||||
|
||||
|
||||
def _ensure_removed_sysmodule(modname):
|
||||
try:
|
||||
del sys.modules[modname]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
class CmdOptions(object):
|
||||
""" holds cmdline options as attributes."""
|
||||
|
||||
def __init__(self, values=()):
|
||||
self.__dict__.update(values)
|
||||
|
||||
def __repr__(self):
|
||||
return "<CmdOptions %r>" %(self.__dict__,)
|
||||
return "<CmdOptions %r>" % (self.__dict__,)
|
||||
|
||||
def copy(self):
|
||||
return CmdOptions(self.__dict__)
|
||||
|
||||
|
||||
class Notset:
|
||||
def __repr__(self):
|
||||
return "<NOTSET>"
|
||||
|
@ -940,14 +951,14 @@ class Config(object):
|
|||
else:
|
||||
style = "native"
|
||||
excrepr = excinfo.getrepr(funcargs=True,
|
||||
showlocals=getattr(option, 'showlocals', False),
|
||||
style=style,
|
||||
)
|
||||
showlocals=getattr(option, 'showlocals', False),
|
||||
style=style,
|
||||
)
|
||||
res = self.hook.pytest_internalerror(excrepr=excrepr,
|
||||
excinfo=excinfo)
|
||||
if not py.builtin.any(res):
|
||||
for line in str(excrepr).split("\n"):
|
||||
sys.stderr.write("INTERNALERROR> %s\n" %line)
|
||||
sys.stderr.write("INTERNALERROR> %s\n" % line)
|
||||
sys.stderr.flush()
|
||||
|
||||
def cwd_relative_nodeid(self, nodeid):
|
||||
|
@ -1074,7 +1085,7 @@ class Config(object):
|
|||
self.known_args_namespace.confcutdir = confcutdir
|
||||
try:
|
||||
self.hook.pytest_load_initial_conftests(early_config=self,
|
||||
args=args, parser=self._parser)
|
||||
args=args, parser=self._parser)
|
||||
except ConftestImportFailure:
|
||||
e = sys.exc_info()[1]
|
||||
if ns.help or ns.version:
|
||||
|
@ -1092,17 +1103,17 @@ class Config(object):
|
|||
myver = pytest.__version__.split(".")
|
||||
if myver < ver:
|
||||
raise pytest.UsageError(
|
||||
"%s:%d: requires pytest-%s, actual pytest-%s'" %(
|
||||
self.inicfg.config.path, self.inicfg.lineof('minversion'),
|
||||
minver, pytest.__version__))
|
||||
"%s:%d: requires pytest-%s, actual pytest-%s'" % (
|
||||
self.inicfg.config.path, self.inicfg.lineof('minversion'),
|
||||
minver, pytest.__version__))
|
||||
|
||||
def parse(self, args, addopts=True):
|
||||
# parse given cmdline arguments into this config object.
|
||||
assert not hasattr(self, 'args'), (
|
||||
"can only parse cmdline args at most once per Config object")
|
||||
"can only parse cmdline args at most once per Config object")
|
||||
self._origargs = args
|
||||
self.hook.pytest_addhooks.call_historic(
|
||||
kwargs=dict(pluginmanager=self.pluginmanager))
|
||||
kwargs=dict(pluginmanager=self.pluginmanager))
|
||||
self._preparse(args, addopts=addopts)
|
||||
# XXX deprecated hook:
|
||||
self.hook.pytest_cmdline_preparse(config=self, args=args)
|
||||
|
@ -1125,7 +1136,7 @@ class Config(object):
|
|||
the first line in its value. """
|
||||
x = self.getini(name)
|
||||
assert isinstance(x, list)
|
||||
x.append(line) # modifies the cached list inline
|
||||
x.append(line) # modifies the cached list inline
|
||||
|
||||
def getini(self, name):
|
||||
""" return configuration value from an :ref:`ini file <inifiles>`. If the
|
||||
|
@ -1142,7 +1153,7 @@ class Config(object):
|
|||
try:
|
||||
description, type, default = self._parser._inidict[name]
|
||||
except KeyError:
|
||||
raise ValueError("unknown configuration value: %r" %(name,))
|
||||
raise ValueError("unknown configuration value: %r" % (name,))
|
||||
value = self._get_override_ini_value(name)
|
||||
if value is None:
|
||||
try:
|
||||
|
@ -1219,7 +1230,7 @@ class Config(object):
|
|||
return default
|
||||
if skip:
|
||||
import pytest
|
||||
pytest.skip("no %r option found" %(name,))
|
||||
pytest.skip("no %r option found" % (name,))
|
||||
raise ValueError("no option named %r" % (name,))
|
||||
|
||||
def getvalue(self, name, path=None):
|
||||
|
@ -1230,12 +1241,14 @@ class Config(object):
|
|||
""" (deprecated, use getoption(skip=True)) """
|
||||
return self.getoption(name, skip=True)
|
||||
|
||||
|
||||
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,
|
||||
|
@ -1361,7 +1374,7 @@ def setns(obj, dic):
|
|||
else:
|
||||
setattr(obj, name, value)
|
||||
obj.__all__.append(name)
|
||||
#if obj != pytest:
|
||||
# if obj != pytest:
|
||||
# pytest.__all__.append(name)
|
||||
setattr(pytest, name, value)
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import pdb
|
|||
import sys
|
||||
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
group._addoption(
|
||||
|
@ -40,6 +39,7 @@ def pytest_configure(config):
|
|||
pytestPDB._pdb_cls = pdb_cls
|
||||
config._cleanup.append(fin)
|
||||
|
||||
|
||||
class pytestPDB:
|
||||
""" Pseudo PDB that defers to the real pdb. """
|
||||
_pluginmanager = None
|
||||
|
|
|
@ -8,7 +8,7 @@ be removed when the time comes.
|
|||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
MAIN_STR_ARGS = 'passing a string to pytest.main() is deprecated, ' \
|
||||
'pass a list of arguments instead.'
|
||||
'pass a list of arguments instead.'
|
||||
|
||||
YIELD_TESTS = 'yield tests are deprecated, and scheduled to be removed in pytest 4.0'
|
||||
|
||||
|
|
|
@ -22,28 +22,29 @@ DOCTEST_REPORT_CHOICES = (
|
|||
DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE,
|
||||
)
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addini('doctest_optionflags', 'option flags for doctests',
|
||||
type="args", default=["ELLIPSIS"])
|
||||
type="args", default=["ELLIPSIS"])
|
||||
parser.addini("doctest_encoding", 'encoding used for doctest files', default="utf-8")
|
||||
group = parser.getgroup("collect")
|
||||
group.addoption("--doctest-modules",
|
||||
action="store_true", default=False,
|
||||
help="run doctests in all .py modules",
|
||||
dest="doctestmodules")
|
||||
action="store_true", default=False,
|
||||
help="run doctests in all .py modules",
|
||||
dest="doctestmodules")
|
||||
group.addoption("--doctest-report",
|
||||
type=str.lower, default="udiff",
|
||||
help="choose another output format for diffs on doctest failure",
|
||||
choices=DOCTEST_REPORT_CHOICES,
|
||||
dest="doctestreport")
|
||||
type=str.lower, default="udiff",
|
||||
help="choose another output format for diffs on doctest failure",
|
||||
choices=DOCTEST_REPORT_CHOICES,
|
||||
dest="doctestreport")
|
||||
group.addoption("--doctest-glob",
|
||||
action="append", default=[], metavar="pat",
|
||||
help="doctests file matching pattern, default: test*.txt",
|
||||
dest="doctestglob")
|
||||
action="append", default=[], metavar="pat",
|
||||
help="doctests file matching pattern, default: test*.txt",
|
||||
dest="doctestglob")
|
||||
group.addoption("--doctest-ignore-import-errors",
|
||||
action="store_true", default=False,
|
||||
help="ignore doctest ImportErrors",
|
||||
dest="doctest_ignore_import_errors")
|
||||
action="store_true", default=False,
|
||||
help="ignore doctest ImportErrors",
|
||||
dest="doctest_ignore_import_errors")
|
||||
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
|
@ -128,11 +129,11 @@ class DoctestItem(pytest.Item):
|
|||
indent = '...'
|
||||
if excinfo.errisinstance(doctest.DocTestFailure):
|
||||
lines += checker.output_difference(example,
|
||||
doctestfailure.got, report_choice).split("\n")
|
||||
doctestfailure.got, report_choice).split("\n")
|
||||
else:
|
||||
inner_excinfo = ExceptionInfo(excinfo.value.exc_info)
|
||||
lines += ["UNEXPECTED EXCEPTION: %s" %
|
||||
repr(inner_excinfo.value)]
|
||||
repr(inner_excinfo.value)]
|
||||
lines += traceback.format_exception(*excinfo.value.exc_info)
|
||||
return ReprFailDoctest(reprlocation, lines)
|
||||
else:
|
||||
|
@ -163,6 +164,7 @@ def get_optionflags(parent):
|
|||
flag_acc |= flag_lookup_table[flag]
|
||||
return flag_acc
|
||||
|
||||
|
||||
class DoctestTextfile(pytest.Module):
|
||||
obj = None
|
||||
|
||||
|
@ -332,7 +334,7 @@ def _fix_spoof_python2(runner, encoding):
|
|||
should patch only doctests for text files because they don't have a way to declare their
|
||||
encoding. Doctests in docstrings from Python modules don't have the same problem given that
|
||||
Python already decoded the strings.
|
||||
|
||||
|
||||
This fixes the problem related in issue #2434.
|
||||
"""
|
||||
from _pytest.compat import _PY2
|
||||
|
|
|
@ -19,6 +19,7 @@ from _pytest.compat import (
|
|||
from _pytest.runner import fail
|
||||
from _pytest.compat import FuncargnamesCompatAttr
|
||||
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
import _pytest.python
|
||||
scopename2class.update({
|
||||
|
@ -38,6 +39,7 @@ scope2props["class"] = scope2props["module"] + ("cls",)
|
|||
scope2props["instance"] = scope2props["class"] + ("instance", )
|
||||
scope2props["function"] = scope2props["instance"] + ("function", "keywords")
|
||||
|
||||
|
||||
def scopeproperty(name=None, doc=None):
|
||||
def decoratescope(func):
|
||||
scopename = name or func.__name__
|
||||
|
@ -69,7 +71,7 @@ def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager):
|
|||
# XXX we can probably avoid this algorithm if we modify CallSpec2
|
||||
# to directly care for creating the fixturedefs within its methods.
|
||||
if not metafunc._calls[0].funcargs:
|
||||
return # this function call does not have direct parametrization
|
||||
return # this function call does not have direct parametrization
|
||||
# collect funcargs of all callspecs into a list of values
|
||||
arg2params = {}
|
||||
arg2scope = {}
|
||||
|
@ -105,16 +107,15 @@ def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager):
|
|||
if node and argname in node._name2pseudofixturedef:
|
||||
arg2fixturedefs[argname] = [node._name2pseudofixturedef[argname]]
|
||||
else:
|
||||
fixturedef = FixtureDef(fixturemanager, '', argname,
|
||||
get_direct_param_fixture_func,
|
||||
arg2scope[argname],
|
||||
valuelist, False, False)
|
||||
fixturedef = FixtureDef(fixturemanager, '', argname,
|
||||
get_direct_param_fixture_func,
|
||||
arg2scope[argname],
|
||||
valuelist, False, False)
|
||||
arg2fixturedefs[argname] = [fixturedef]
|
||||
if node is not None:
|
||||
node._name2pseudofixturedef[argname] = fixturedef
|
||||
|
||||
|
||||
|
||||
def getfixturemarker(obj):
|
||||
""" return fixturemarker or None if it doesn't exist or raised
|
||||
exceptions."""
|
||||
|
@ -126,7 +127,6 @@ def getfixturemarker(obj):
|
|||
return None
|
||||
|
||||
|
||||
|
||||
def get_parametrized_fixture_keys(item, scopenum):
|
||||
""" return list of keys for all parametrized arguments which match
|
||||
the specified scope. """
|
||||
|
@ -166,15 +166,16 @@ def reorder_items(items):
|
|||
d[item] = keys
|
||||
return reorder_items_atscope(items, set(), argkeys_cache, 0)
|
||||
|
||||
|
||||
def reorder_items_atscope(items, ignore, argkeys_cache, scopenum):
|
||||
if scopenum >= scopenum_function or len(items) < 3:
|
||||
return items
|
||||
items_done = []
|
||||
while 1:
|
||||
items_before, items_same, items_other, newignore = \
|
||||
slice_items(items, ignore, argkeys_cache[scopenum])
|
||||
slice_items(items, ignore, argkeys_cache[scopenum])
|
||||
items_before = reorder_items_atscope(
|
||||
items_before, ignore, argkeys_cache,scopenum+1)
|
||||
items_before, ignore, argkeys_cache, scopenum + 1)
|
||||
if items_same is None:
|
||||
# nothing to reorder in this scope
|
||||
assert items_other is None
|
||||
|
@ -205,7 +206,7 @@ def slice_items(items, ignore, scoped_argkeys_cache):
|
|||
for item in it:
|
||||
argkeys = scoped_argkeys_cache.get(item)
|
||||
if argkeys and slicing_argkey in argkeys and \
|
||||
slicing_argkey not in ignore:
|
||||
slicing_argkey not in ignore:
|
||||
items_same.append(item)
|
||||
else:
|
||||
items_other.append(item)
|
||||
|
@ -237,10 +238,10 @@ def fillfixtures(function):
|
|||
request._fillfixtures()
|
||||
|
||||
|
||||
|
||||
def get_direct_param_fixture_func(request):
|
||||
return request.param
|
||||
|
||||
|
||||
class FuncFixtureInfo:
|
||||
def __init__(self, argnames, names_closure, name2fixturedefs):
|
||||
self.argnames = argnames
|
||||
|
@ -279,7 +280,6 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
""" underlying collection node (depends on current request scope)"""
|
||||
return self._getscopeitem(self.scope)
|
||||
|
||||
|
||||
def _getnextfixturedef(self, argname):
|
||||
fixturedefs = self._arg2fixturedefs.get(argname, None)
|
||||
if fixturedefs is None:
|
||||
|
@ -301,7 +301,6 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
""" the pytest config object associated with this request. """
|
||||
return self._pyfuncitem.config
|
||||
|
||||
|
||||
@scopeproperty()
|
||||
def function(self):
|
||||
""" test function object if the request has a per-function scope. """
|
||||
|
@ -397,7 +396,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
:arg extrakey: added to internal caching key of (funcargname, scope).
|
||||
"""
|
||||
if not hasattr(self.config, '_setupcache'):
|
||||
self.config._setupcache = {} # XXX weakref?
|
||||
self.config._setupcache = {} # XXX weakref?
|
||||
cachekey = (self.fixturename, self._getscopeitem(scope), extrakey)
|
||||
cache = self.config._setupcache
|
||||
try:
|
||||
|
@ -527,8 +526,8 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
fail("ScopeMismatch: You tried to access the %r scoped "
|
||||
"fixture %r with a %r scoped request object, "
|
||||
"involved factories\n%s" % (
|
||||
(requested_scope, argname, invoking_scope, "\n".join(lines))),
|
||||
pytrace=False)
|
||||
(requested_scope, argname, invoking_scope, "\n".join(lines))),
|
||||
pytrace=False)
|
||||
|
||||
def _factorytraceback(self):
|
||||
lines = []
|
||||
|
@ -553,12 +552,13 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
return node
|
||||
|
||||
def __repr__(self):
|
||||
return "<FixtureRequest for %r>" %(self.node)
|
||||
return "<FixtureRequest for %r>" % (self.node)
|
||||
|
||||
|
||||
class SubRequest(FixtureRequest):
|
||||
""" a sub request for handling getting a fixture from a
|
||||
test function/fixture. """
|
||||
|
||||
def __init__(self, request, scope, param, param_index, fixturedef):
|
||||
self._parent_request = request
|
||||
self.fixturename = fixturedef.argname
|
||||
|
@ -569,7 +569,7 @@ class SubRequest(FixtureRequest):
|
|||
self._fixturedef = fixturedef
|
||||
self.addfinalizer = fixturedef.addfinalizer
|
||||
self._pyfuncitem = request._pyfuncitem
|
||||
self._fixture_values = request._fixture_values
|
||||
self._fixture_values = request._fixture_values
|
||||
self._fixture_defs = request._fixture_defs
|
||||
self._arg2fixturedefs = request._arg2fixturedefs
|
||||
self._arg2index = request._arg2index
|
||||
|
@ -609,6 +609,7 @@ def scope2index(scope, descr, where=None):
|
|||
|
||||
class FixtureLookupError(LookupError):
|
||||
""" could not return a requested Fixture (missing or invalid). """
|
||||
|
||||
def __init__(self, argname, request, msg=None):
|
||||
self.argname = argname
|
||||
self.request = request
|
||||
|
@ -631,9 +632,9 @@ class FixtureLookupError(LookupError):
|
|||
lines, _ = inspect.getsourcelines(get_real_func(function))
|
||||
except (IOError, IndexError, TypeError):
|
||||
error_msg = "file %s, line %s: source code not available"
|
||||
addline(error_msg % (fspath, lineno+1))
|
||||
addline(error_msg % (fspath, lineno + 1))
|
||||
else:
|
||||
addline("file %s, line %s" % (fspath, lineno+1))
|
||||
addline("file %s, line %s" % (fspath, lineno + 1))
|
||||
for i, line in enumerate(lines):
|
||||
line = line.rstrip()
|
||||
addline(" " + line)
|
||||
|
@ -649,7 +650,7 @@ class FixtureLookupError(LookupError):
|
|||
if faclist and name not in available:
|
||||
available.append(name)
|
||||
msg = "fixture %r not found" % (self.argname,)
|
||||
msg += "\n available fixtures: %s" %(", ".join(sorted(available)),)
|
||||
msg += "\n available fixtures: %s" % (", ".join(sorted(available)),)
|
||||
msg += "\n use 'pytest --fixtures [testpath]' for help on them."
|
||||
|
||||
return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname)
|
||||
|
@ -675,12 +676,12 @@ class FixtureLookupErrorRepr(TerminalRepr):
|
|||
tw.line('{0} {1}'.format(FormattedExcinfo.flow_marker,
|
||||
line.strip()), red=True)
|
||||
tw.line()
|
||||
tw.line("%s:%d" % (self.filename, self.firstlineno+1))
|
||||
tw.line("%s:%d" % (self.filename, self.firstlineno + 1))
|
||||
|
||||
|
||||
def fail_fixturefunc(fixturefunc, msg):
|
||||
fs, lineno = getfslineno(fixturefunc)
|
||||
location = "%s:%s" % (fs, lineno+1)
|
||||
location = "%s:%s" % (fs, lineno + 1)
|
||||
source = _pytest._code.Source(fixturefunc)
|
||||
fail(msg + ":\n\n" + str(source.indent()) + "\n" + location,
|
||||
pytrace=False)
|
||||
|
@ -699,7 +700,7 @@ def call_fixture_func(fixturefunc, request, kwargs):
|
|||
pass
|
||||
else:
|
||||
fail_fixturefunc(fixturefunc,
|
||||
"yield_fixture function has more than one 'yield'")
|
||||
"yield_fixture function has more than one 'yield'")
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
else:
|
||||
|
@ -709,6 +710,7 @@ def call_fixture_func(fixturefunc, request, kwargs):
|
|||
|
||||
class FixtureDef:
|
||||
""" A container for a factory definition. """
|
||||
|
||||
def __init__(self, fixturemanager, baseid, argname, func, scope, params,
|
||||
unittest=False, ids=None):
|
||||
self._fixturemanager = fixturemanager
|
||||
|
@ -783,6 +785,7 @@ class FixtureDef:
|
|||
return ("<FixtureDef name=%r scope=%r baseid=%r >" %
|
||||
(self.argname, self.scope, self.baseid))
|
||||
|
||||
|
||||
def pytest_fixture_setup(fixturedef, request):
|
||||
""" Execution of fixture setup. """
|
||||
kwargs = {}
|
||||
|
@ -826,12 +829,11 @@ class FixtureFunctionMarker:
|
|||
def __call__(self, function):
|
||||
if isclass(function):
|
||||
raise ValueError(
|
||||
"class fixtures not supported (may be in the future)")
|
||||
"class fixtures not supported (may be in the future)")
|
||||
function._pytestfixturefunction = self
|
||||
return function
|
||||
|
||||
|
||||
|
||||
def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
|
||||
""" (return a) decorator to mark a fixture factory function.
|
||||
|
||||
|
@ -870,10 +872,10 @@ def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
|
|||
instead of ``return``. In this case, the code block after the ``yield`` statement is executed
|
||||
as teardown code regardless of the test outcome. A fixture function must yield exactly once.
|
||||
"""
|
||||
if callable(scope) and params is None and autouse == False:
|
||||
if callable(scope) and params is None and autouse is False:
|
||||
# direct decoration
|
||||
return FixtureFunctionMarker(
|
||||
"function", params, autouse, name=name)(scope)
|
||||
"function", params, autouse, name=name)(scope)
|
||||
if params is not None and not isinstance(params, (list, tuple)):
|
||||
params = list(params)
|
||||
return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)
|
||||
|
@ -888,7 +890,7 @@ def yield_fixture(scope="function", params=None, autouse=False, ids=None, name=N
|
|||
if callable(scope) and params is None and not autouse:
|
||||
# direct decoration
|
||||
return FixtureFunctionMarker(
|
||||
"function", params, autouse, ids=ids, name=name)(scope)
|
||||
"function", params, autouse, ids=ids, name=name)(scope)
|
||||
else:
|
||||
return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)
|
||||
|
||||
|
@ -947,7 +949,6 @@ class FixtureManager:
|
|||
self._nodeid_and_autousenames = [("", self.config.getini("usefixtures"))]
|
||||
session.config.pluginmanager.register(self, "funcmanage")
|
||||
|
||||
|
||||
def getfixtureinfo(self, node, func, cls, funcargs=True):
|
||||
if funcargs and not hasattr(node, "nofuncargs"):
|
||||
if cls is not None:
|
||||
|
@ -989,7 +990,7 @@ class FixtureManager:
|
|||
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)
|
||||
|
@ -1126,4 +1127,3 @@ class FixtureManager:
|
|||
for fixturedef in fixturedefs:
|
||||
if nodeid.startswith(fixturedef.baseid):
|
||||
yield fixturedef
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ pytest
|
|||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
|
||||
|
||||
def freeze_includes():
|
||||
"""
|
||||
Returns a list of module names used by py.test that should be
|
||||
|
|
|
@ -4,7 +4,8 @@ from __future__ import absolute_import, division, print_function
|
|||
import py
|
||||
import pytest
|
||||
from _pytest.config import PrintHelp
|
||||
import os, sys
|
||||
import os
|
||||
import sys
|
||||
from argparse import Action
|
||||
|
||||
|
||||
|
@ -41,20 +42,20 @@ class HelpAction(Action):
|
|||
def pytest_addoption(parser):
|
||||
group = parser.getgroup('debugconfig')
|
||||
group.addoption('--version', action="store_true",
|
||||
help="display pytest lib version and import information.")
|
||||
help="display pytest lib version and import information.")
|
||||
group._addoption("-h", "--help", action=HelpAction, dest="help",
|
||||
help="show help message and configuration info")
|
||||
group._addoption('-p', action="append", dest="plugins", default = [],
|
||||
metavar="name",
|
||||
help="early-load given plugin (multi-allowed). "
|
||||
"To avoid loading of plugins, use the `no:` prefix, e.g. "
|
||||
"`no:doctest`.")
|
||||
help="show help message and configuration info")
|
||||
group._addoption('-p', action="append", dest="plugins", default=[],
|
||||
metavar="name",
|
||||
help="early-load given plugin (multi-allowed). "
|
||||
"To avoid loading of plugins, use the `no:` prefix, e.g. "
|
||||
"`no:doctest`.")
|
||||
group.addoption('--traceconfig', '--trace-config',
|
||||
action="store_true", default=False,
|
||||
help="trace considerations of conftest.py files."),
|
||||
action="store_true", default=False,
|
||||
help="trace considerations of conftest.py files."),
|
||||
group.addoption('--debug',
|
||||
action="store_true", dest="debug", default=False,
|
||||
help="store internal tracing debug information in 'pytestdebug.log'.")
|
||||
action="store_true", dest="debug", default=False,
|
||||
help="store internal tracing debug information in 'pytestdebug.log'.")
|
||||
group._addoption(
|
||||
'-o', '--override-ini', nargs='*', dest="override_ini",
|
||||
action="append",
|
||||
|
@ -69,10 +70,10 @@ def pytest_cmdline_parse():
|
|||
path = os.path.abspath("pytestdebug.log")
|
||||
debugfile = open(path, 'w')
|
||||
debugfile.write("versions pytest-%s, py-%s, "
|
||||
"python-%s\ncwd=%s\nargs=%s\n\n" %(
|
||||
pytest.__version__, py.__version__,
|
||||
".".join(map(str, sys.version_info)),
|
||||
os.getcwd(), config._origargs))
|
||||
"python-%s\ncwd=%s\nargs=%s\n\n" % (
|
||||
pytest.__version__, py.__version__,
|
||||
".".join(map(str, sys.version_info)),
|
||||
os.getcwd(), config._origargs))
|
||||
config.trace.root.setwriter(debugfile.write)
|
||||
undo_tracing = config.pluginmanager.enable_tracing()
|
||||
sys.stderr.write("writing pytestdebug information to %s\n" % path)
|
||||
|
@ -86,11 +87,12 @@ def pytest_cmdline_parse():
|
|||
|
||||
config.add_cleanup(unset_tracing)
|
||||
|
||||
|
||||
def pytest_cmdline_main(config):
|
||||
if config.option.version:
|
||||
p = py.path.local(pytest.__file__)
|
||||
sys.stderr.write("This is pytest version %s, imported from %s\n" %
|
||||
(pytest.__version__, p))
|
||||
(pytest.__version__, p))
|
||||
plugininfo = getpluginversioninfo(config)
|
||||
if plugininfo:
|
||||
for line in plugininfo:
|
||||
|
@ -102,6 +104,7 @@ def pytest_cmdline_main(config):
|
|||
config._ensure_unconfigure()
|
||||
return 0
|
||||
|
||||
|
||||
def showhelp(config):
|
||||
reporter = config.pluginmanager.get_plugin('terminalreporter')
|
||||
tw = reporter._tw
|
||||
|
@ -117,7 +120,7 @@ def showhelp(config):
|
|||
if type is None:
|
||||
type = "string"
|
||||
spec = "%s (%s)" % (name, type)
|
||||
line = " %-24s %s" %(spec, help)
|
||||
line = " %-24s %s" % (spec, help)
|
||||
tw.line(line[:tw.fullwidth])
|
||||
|
||||
tw.line()
|
||||
|
@ -146,6 +149,7 @@ conftest_options = [
|
|||
('pytest_plugins', 'list of plugin names to load'),
|
||||
]
|
||||
|
||||
|
||||
def getpluginversioninfo(config):
|
||||
lines = []
|
||||
plugininfo = config.pluginmanager.list_plugin_distinfo()
|
||||
|
@ -157,11 +161,12 @@ def getpluginversioninfo(config):
|
|||
lines.append(" " + content)
|
||||
return lines
|
||||
|
||||
|
||||
def pytest_report_header(config):
|
||||
lines = []
|
||||
if config.option.debug or config.option.traceconfig:
|
||||
lines.append("using: pytest-%s pylib-%s" %
|
||||
(pytest.__version__,py.__version__))
|
||||
(pytest.__version__, py.__version__))
|
||||
|
||||
verinfo = getpluginversioninfo(config)
|
||||
if verinfo:
|
||||
|
@ -175,5 +180,5 @@ def pytest_report_header(config):
|
|||
r = plugin.__file__
|
||||
else:
|
||||
r = repr(plugin)
|
||||
lines.append(" %-20s: %s" %(name, r))
|
||||
lines.append(" %-20s: %s" % (name, r))
|
||||
return lines
|
||||
|
|
|
@ -8,6 +8,7 @@ hookspec = HookspecMarker("pytest")
|
|||
# Initialization hooks called for every plugin
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@hookspec(historic=True)
|
||||
def pytest_addhooks(pluginmanager):
|
||||
"""called at plugin registration time to allow adding new hooks via a call to
|
||||
|
@ -23,6 +24,7 @@ def pytest_namespace():
|
|||
time.
|
||||
"""
|
||||
|
||||
|
||||
@hookspec(historic=True)
|
||||
def pytest_plugin_registered(plugin, manager):
|
||||
""" a new pytest plugin got registered. """
|
||||
|
@ -58,6 +60,7 @@ def pytest_addoption(parser):
|
|||
via (deprecated) ``pytest.config``.
|
||||
"""
|
||||
|
||||
|
||||
@hookspec(historic=True)
|
||||
def pytest_configure(config):
|
||||
"""
|
||||
|
@ -79,15 +82,18 @@ def pytest_configure(config):
|
|||
# discoverable conftest.py local plugins.
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_cmdline_parse(pluginmanager, args):
|
||||
"""return initialized config object, parsing the specified args.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_cmdline_preparse(config, args):
|
||||
"""(deprecated) modify command line arguments before option parsing. """
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_cmdline_main(config):
|
||||
""" called for performing the main command line action. The default
|
||||
|
@ -95,6 +101,7 @@ def pytest_cmdline_main(config):
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_load_initial_conftests(early_config, parser, args):
|
||||
""" implements the loading of initial conftest files ahead
|
||||
of command line option parsing. """
|
||||
|
@ -110,13 +117,16 @@ def pytest_collection(session):
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(session, config, items):
|
||||
""" called after collection has been performed, may filter or re-order
|
||||
the items in-place."""
|
||||
|
||||
|
||||
def pytest_collection_finish(session):
|
||||
""" called after collection has been performed and modified. """
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_ignore_collect(path, config):
|
||||
""" return True to prevent considering this path for collection.
|
||||
|
@ -126,29 +136,37 @@ def pytest_ignore_collect(path, config):
|
|||
Stops at first non-None result, see :ref:`firstresult`
|
||||
"""
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_collect_directory(path, parent):
|
||||
""" called before traversing a directory for collection files.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
""" return collection Node or None for the given path. Any new node
|
||||
needs to have the specified ``parent`` as a parent."""
|
||||
|
||||
# logging hooks for collection
|
||||
|
||||
|
||||
def pytest_collectstart(collector):
|
||||
""" collector starts collecting. """
|
||||
|
||||
|
||||
def pytest_itemcollected(item):
|
||||
""" we just collected a test item. """
|
||||
|
||||
|
||||
def pytest_collectreport(report):
|
||||
""" collector finished collecting. """
|
||||
|
||||
|
||||
def pytest_deselected(items):
|
||||
""" called for test items deselected by keyword. """
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_make_collect_report(collector):
|
||||
""" perform ``collector.collect()`` and return a CollectReport.
|
||||
|
@ -159,6 +177,7 @@ def pytest_make_collect_report(collector):
|
|||
# Python test function related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_pycollect_makemodule(path, parent):
|
||||
""" return a Module collector or None for the given path.
|
||||
|
@ -168,21 +187,25 @@ def pytest_pycollect_makemodule(path, parent):
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
""" return custom item/collector for a python object in a module, or None.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_pyfunc_call(pyfuncitem):
|
||||
""" call underlying test function.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
""" generate (multiple) parametrized calls to a test function."""
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_make_parametrize_id(config, val, argname):
|
||||
"""Return a user-friendly string representation of the given ``val`` that will be used
|
||||
|
@ -195,6 +218,7 @@ def pytest_make_parametrize_id(config, val, argname):
|
|||
# generic runtest related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_runtestloop(session):
|
||||
""" called for performing the main runtest loop
|
||||
|
@ -202,9 +226,11 @@ def pytest_runtestloop(session):
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_itemstart(item, node):
|
||||
""" (deprecated, use pytest_runtest_logstart). """
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_runtest_protocol(item, nextitem):
|
||||
""" implements the runtest_setup/call/teardown protocol for
|
||||
|
@ -222,15 +248,19 @@ def pytest_runtest_protocol(item, nextitem):
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_runtest_logstart(nodeid, location):
|
||||
""" signal the start of running a single test item. """
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
""" called before ``pytest_runtest_call(item)``. """
|
||||
|
||||
|
||||
def pytest_runtest_call(item):
|
||||
""" called to execute the test ``item``. """
|
||||
|
||||
|
||||
def pytest_runtest_teardown(item, nextitem):
|
||||
""" called after ``pytest_runtest_call``.
|
||||
|
||||
|
@ -240,6 +270,7 @@ def pytest_runtest_teardown(item, nextitem):
|
|||
so that nextitem only needs to call setup-functions.
|
||||
"""
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
""" return a :py:class:`_pytest.runner.TestReport` object
|
||||
|
@ -248,6 +279,7 @@ def pytest_runtest_makereport(item, call):
|
|||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_runtest_logreport(report):
|
||||
""" process a test setup/call/teardown report relating to
|
||||
the respective phase of executing a test. """
|
||||
|
@ -256,12 +288,14 @@ def pytest_runtest_logreport(report):
|
|||
# Fixture related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_fixture_setup(fixturedef, request):
|
||||
""" performs fixture setup execution.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_fixture_post_finalizer(fixturedef):
|
||||
""" called after fixture teardown, but before the cache is cleared so
|
||||
the fixture result cache ``fixturedef.cached_result`` can
|
||||
|
@ -271,12 +305,15 @@ def pytest_fixture_post_finalizer(fixturedef):
|
|||
# test session related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
""" before session.main() is called. """
|
||||
|
||||
|
||||
def pytest_sessionfinish(session, exitstatus):
|
||||
""" whole test run finishes. """
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
""" called before test process is exited. """
|
||||
|
||||
|
@ -298,6 +335,7 @@ def pytest_assertrepr_compare(config, op, left, right):
|
|||
# hooks for influencing reporting (invoked from _pytest_terminal)
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
def pytest_report_header(config, startdir):
|
||||
""" return a string to be displayed as header info for terminal reporting.
|
||||
|
||||
|
@ -308,12 +346,14 @@ def pytest_report_header(config, startdir):
|
|||
:ref:`discovers plugins during startup <pluginorder>`.
|
||||
"""
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_report_teststatus(report):
|
||||
""" return result-category, shortletter and verbose word for reporting.
|
||||
|
||||
Stops at first non-None result, see :ref:`firstresult` """
|
||||
|
||||
|
||||
def pytest_terminal_summary(terminalreporter, exitstatus):
|
||||
""" add additional section in terminal summary reporting. """
|
||||
|
||||
|
@ -328,6 +368,7 @@ def pytest_logwarning(message, code, nodeid, fslocation):
|
|||
# doctest hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@hookspec(firstresult=True)
|
||||
def pytest_doctest_prepare_content(content):
|
||||
""" return processed content for a given doctest
|
||||
|
@ -338,12 +379,15 @@ def pytest_doctest_prepare_content(content):
|
|||
# error handling and internal debugging hooks
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
def pytest_internalerror(excrepr, excinfo):
|
||||
""" called for internal errors. """
|
||||
|
||||
|
||||
def pytest_keyboard_interrupt(excinfo):
|
||||
""" called for keyboard interrupt. """
|
||||
|
||||
|
||||
def pytest_exception_interact(node, call, report):
|
||||
"""called when an exception was raised which can potentially be
|
||||
interactively handled.
|
||||
|
@ -352,6 +396,7 @@ def pytest_exception_interact(node, call, report):
|
|||
that is not an internal exception like ``skip.Exception``.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_enter_pdb(config):
|
||||
""" called upon pdb.set_trace(), can be used by plugins to take special
|
||||
action just before the python debugger enters in interactive mode.
|
||||
|
|
|
@ -378,8 +378,8 @@ class LogXML(object):
|
|||
close_report = next(
|
||||
(rep for rep in self.open_reports
|
||||
if (rep.nodeid == report.nodeid and
|
||||
getattr(rep, "item_index", None) == report_ii and
|
||||
getattr(rep, "worker_id", None) == report_wid
|
||||
getattr(rep, "item_index", None) == report_ii and
|
||||
getattr(rep, "worker_id", None) == report_wid
|
||||
)
|
||||
), None)
|
||||
if close_report:
|
||||
|
@ -444,9 +444,9 @@ class LogXML(object):
|
|||
"""
|
||||
if self.global_properties:
|
||||
return Junit.properties(
|
||||
[
|
||||
Junit.property(name=name, value=value)
|
||||
for name, value in self.global_properties
|
||||
]
|
||||
[
|
||||
Junit.property(name=name, value=value)
|
||||
for name, value in self.global_properties
|
||||
]
|
||||
)
|
||||
return ''
|
||||
|
|
|
@ -29,53 +29,54 @@ EXIT_NOTESTSCOLLECTED = 5
|
|||
|
||||
def pytest_addoption(parser):
|
||||
parser.addini("norecursedirs", "directory patterns to avoid for recursion",
|
||||
type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv'])
|
||||
parser.addini("testpaths", "directories to search for tests when no files or directories are given in the command line.",
|
||||
type="args", default=[])
|
||||
#parser.addini("dirpatterns",
|
||||
type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv'])
|
||||
parser.addini("testpaths", "directories to search for tests when no files or directories are given in the "
|
||||
"command line.",
|
||||
type="args", default=[])
|
||||
# parser.addini("dirpatterns",
|
||||
# "patterns specifying possible locations of test files",
|
||||
# type="linelist", default=["**/test_*.txt",
|
||||
# "**/test_*.py", "**/*_test.py"]
|
||||
#)
|
||||
# )
|
||||
group = parser.getgroup("general", "running and selection options")
|
||||
group._addoption('-x', '--exitfirst', action="store_const",
|
||||
dest="maxfail", const=1,
|
||||
help="exit instantly on first error or failed test."),
|
||||
dest="maxfail", const=1,
|
||||
help="exit instantly on first error or failed test."),
|
||||
group._addoption('--maxfail', metavar="num",
|
||||
action="store", type=int, dest="maxfail", default=0,
|
||||
help="exit after first num failures or errors.")
|
||||
action="store", type=int, dest="maxfail", default=0,
|
||||
help="exit after first num failures or errors.")
|
||||
group._addoption('--strict', action="store_true",
|
||||
help="marks not registered in configuration file raise errors.")
|
||||
help="marks not registered in configuration file raise errors.")
|
||||
group._addoption("-c", metavar="file", type=str, dest="inifilename",
|
||||
help="load configuration from `file` instead of trying to locate one of the implicit configuration files.")
|
||||
help="load configuration from `file` instead of trying to locate one of the implicit "
|
||||
"configuration files.")
|
||||
group._addoption("--continue-on-collection-errors", action="store_true",
|
||||
default=False, dest="continue_on_collection_errors",
|
||||
help="Force test execution even if collection errors occur.")
|
||||
default=False, dest="continue_on_collection_errors",
|
||||
help="Force test execution even if collection errors occur.")
|
||||
|
||||
group = parser.getgroup("collect", "collection")
|
||||
group.addoption('--collectonly', '--collect-only', action="store_true",
|
||||
help="only collect tests, don't execute them."),
|
||||
help="only collect tests, don't execute them."),
|
||||
group.addoption('--pyargs', action="store_true",
|
||||
help="try to interpret all arguments as python packages.")
|
||||
help="try to interpret all arguments as python packages.")
|
||||
group.addoption("--ignore", action="append", metavar="path",
|
||||
help="ignore path during collection (multi-allowed).")
|
||||
help="ignore path during collection (multi-allowed).")
|
||||
# when changing this to --conf-cut-dir, config.py Conftest.setinitial
|
||||
# needs upgrading as well
|
||||
group.addoption('--confcutdir', dest="confcutdir", default=None,
|
||||
metavar="dir", type=functools.partial(directory_arg, optname="--confcutdir"),
|
||||
help="only load conftest.py's relative to specified dir.")
|
||||
metavar="dir", type=functools.partial(directory_arg, optname="--confcutdir"),
|
||||
help="only load conftest.py's relative to specified dir.")
|
||||
group.addoption('--noconftest', action="store_true",
|
||||
dest="noconftest", default=False,
|
||||
help="Don't load any conftest.py files.")
|
||||
dest="noconftest", default=False,
|
||||
help="Don't load any conftest.py files.")
|
||||
group.addoption('--keepduplicates', '--keep-duplicates', action="store_true",
|
||||
dest="keepduplicates", default=False,
|
||||
help="Keep duplicate tests.")
|
||||
dest="keepduplicates", default=False,
|
||||
help="Keep duplicate tests.")
|
||||
|
||||
group = parser.getgroup("debugconfig",
|
||||
"test session debugging and configuration")
|
||||
"test session debugging and configuration")
|
||||
group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir",
|
||||
help="base temporary directory for this test run.")
|
||||
|
||||
help="base temporary directory for this test run.")
|
||||
|
||||
|
||||
def pytest_namespace():
|
||||
|
@ -88,7 +89,7 @@ def pytest_namespace():
|
|||
|
||||
|
||||
def pytest_configure(config):
|
||||
__import__('pytest').config = config # compatibiltiy
|
||||
__import__('pytest').config = config # compatibiltiy
|
||||
|
||||
|
||||
def wrap_session(config, doit):
|
||||
|
@ -160,7 +161,7 @@ def pytest_runtestloop(session):
|
|||
return True
|
||||
|
||||
for i, item in enumerate(session.items):
|
||||
nextitem = session.items[i+1] if i+1 < len(session.items) else None
|
||||
nextitem = session.items[i + 1] if i + 1 < len(session.items) else None
|
||||
item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
|
||||
if session.shouldstop:
|
||||
raise session.Interrupted(session.shouldstop)
|
||||
|
@ -200,6 +201,7 @@ class FSHookProxy:
|
|||
self.__dict__[name] = x
|
||||
return x
|
||||
|
||||
|
||||
class _CompatProperty(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
@ -216,7 +218,6 @@ class _CompatProperty(object):
|
|||
return getattr(__import__('pytest'), self.name)
|
||||
|
||||
|
||||
|
||||
class NodeKeywords(MappingMixin):
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
|
@ -307,8 +308,8 @@ class Node(object):
|
|||
return cls
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s %r>" %(self.__class__.__name__,
|
||||
getattr(self, 'name', None))
|
||||
return "<%s %r>" % (self.__class__.__name__,
|
||||
getattr(self, 'name', None))
|
||||
|
||||
def warn(self, code, message):
|
||||
""" generate a warning with the given code and message for this
|
||||
|
@ -429,7 +430,7 @@ class Node(object):
|
|||
return excinfo.value.formatrepr()
|
||||
tbfilter = True
|
||||
if self.config.option.fulltrace:
|
||||
style="long"
|
||||
style = "long"
|
||||
else:
|
||||
tb = _pytest._code.Traceback([excinfo.traceback[-1]])
|
||||
self._prunetraceback(excinfo)
|
||||
|
@ -457,6 +458,7 @@ class Node(object):
|
|||
|
||||
repr_failure = _repr_failure_py
|
||||
|
||||
|
||||
class Collector(Node):
|
||||
""" Collector instances create children through collect()
|
||||
and thus iteratively build a tree.
|
||||
|
@ -486,9 +488,10 @@ class Collector(Node):
|
|||
ntraceback = ntraceback.cut(excludepath=tracebackcutdir)
|
||||
excinfo.traceback = ntraceback.filter()
|
||||
|
||||
|
||||
class FSCollector(Collector):
|
||||
def __init__(self, fspath, parent=None, config=None, session=None):
|
||||
fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
|
||||
fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
|
||||
name = fspath.basename
|
||||
if parent is not None:
|
||||
rel = fspath.relto(parent.fspath)
|
||||
|
@ -504,9 +507,11 @@ class FSCollector(Collector):
|
|||
relpath = relpath.replace(os.sep, "/")
|
||||
return relpath
|
||||
|
||||
|
||||
class File(FSCollector):
|
||||
""" base class for collecting tests from a file. """
|
||||
|
||||
|
||||
class Item(Node):
|
||||
""" a basic test invocation item. Note that for a single function
|
||||
there might be multiple test invocation items.
|
||||
|
@ -556,12 +561,15 @@ class Item(Node):
|
|||
self._location = location
|
||||
return location
|
||||
|
||||
|
||||
class NoMatch(Exception):
|
||||
""" raised if matching cannot locate a matching names. """
|
||||
|
||||
|
||||
class Interrupted(KeyboardInterrupt):
|
||||
""" signals an interrupted test run. """
|
||||
__module__ = 'builtins' # for py3
|
||||
__module__ = 'builtins' # for py3
|
||||
|
||||
|
||||
class Session(FSCollector):
|
||||
Interrupted = Interrupted
|
||||
|
@ -618,7 +626,7 @@ class Session(FSCollector):
|
|||
items = self._perform_collect(args, genitems)
|
||||
self.config.pluginmanager.check_pending()
|
||||
hook.pytest_collection_modifyitems(session=self,
|
||||
config=self.config, items=items)
|
||||
config=self.config, items=items)
|
||||
finally:
|
||||
hook.pytest_collection_finish(session=self)
|
||||
self.testscollected = len(items)
|
||||
|
|
|
@ -155,6 +155,7 @@ def pytest_collection_modifyitems(items, config):
|
|||
class MarkMapping:
|
||||
"""Provides a local mapping for markers where item access
|
||||
resolves to True if the marker is present. """
|
||||
|
||||
def __init__(self, keywords):
|
||||
mymarks = set()
|
||||
for key, value in keywords.items():
|
||||
|
@ -170,6 +171,7 @@ class KeywordMapping:
|
|||
"""Provides a local mapping for keywords.
|
||||
Given a list of names, map any substring of one of these names to True.
|
||||
"""
|
||||
|
||||
def __init__(self, names):
|
||||
self._names = names
|
||||
|
||||
|
@ -243,7 +245,6 @@ class MarkGenerator:
|
|||
on the ``test_function`` object. """
|
||||
_config = None
|
||||
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name[0] == "_":
|
||||
raise AttributeError("Marker name must NOT start with underscore")
|
||||
|
@ -270,6 +271,7 @@ def istestfunc(func):
|
|||
return hasattr(func, "__call__") and \
|
||||
getattr(func, "__name__", "<lambda>") != "<lambda>"
|
||||
|
||||
|
||||
class MarkDecorator:
|
||||
""" A decorator for test functions and test classes. When applied
|
||||
it will create :class:`MarkInfo` objects which may be
|
||||
|
@ -303,6 +305,7 @@ class MarkDecorator:
|
|||
additional keyword or positional arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, mark):
|
||||
assert isinstance(mark, Mark), repr(mark)
|
||||
self.mark = mark
|
||||
|
@ -313,7 +316,7 @@ class MarkDecorator:
|
|||
|
||||
@property
|
||||
def markname(self):
|
||||
return self.name # for backward-compat (2.4.1 had this attr)
|
||||
return self.name # for backward-compat (2.4.1 had this attr)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.mark == other.mark
|
||||
|
@ -352,9 +355,6 @@ class MarkDecorator:
|
|||
return self.__class__(self.mark.combined_with(mark))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Mark(namedtuple('Mark', 'name, args, kwargs')):
|
||||
|
||||
def combined_with(self, other):
|
||||
|
@ -366,6 +366,7 @@ class Mark(namedtuple('Mark', 'name, args, kwargs')):
|
|||
|
||||
class MarkInfo(object):
|
||||
""" Marking object created by :class:`MarkDecorator` instances. """
|
||||
|
||||
def __init__(self, mark):
|
||||
assert isinstance(mark, Mark), repr(mark)
|
||||
self.combined = mark
|
||||
|
|
|
@ -71,9 +71,9 @@ def annotated_getattr(obj, name, ann):
|
|||
obj = getattr(obj, name)
|
||||
except AttributeError:
|
||||
raise AttributeError(
|
||||
'%r object at %s has no attribute %r' % (
|
||||
type(obj).__name__, ann, name
|
||||
)
|
||||
'%r object at %s has no attribute %r' % (
|
||||
type(obj).__name__, ann, name
|
||||
)
|
||||
)
|
||||
return obj
|
||||
|
||||
|
|
|
@ -38,14 +38,15 @@ def pytest_runtest_setup(item):
|
|||
if not call_optional(item.obj, 'setup'):
|
||||
# call module level setup if there is no object level one
|
||||
call_optional(item.parent.obj, 'setup')
|
||||
#XXX this implies we only call teardown when setup worked
|
||||
# XXX this implies we only call teardown when setup worked
|
||||
item.session._setupstate.addfinalizer((lambda: teardown_nose(item)), item)
|
||||
|
||||
|
||||
def teardown_nose(item):
|
||||
if is_potential_nosetest(item):
|
||||
if not call_optional(item.obj, 'teardown'):
|
||||
call_optional(item.parent.obj, 'teardown')
|
||||
#if hasattr(item.parent, '_nosegensetup'):
|
||||
# if hasattr(item.parent, '_nosegensetup'):
|
||||
# #call_optional(item._nosegensetup, 'teardown')
|
||||
# del item.parent._nosegensetup
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ import tempfile
|
|||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("terminal reporting")
|
||||
group._addoption('--pastebin', metavar="mode",
|
||||
action='store', dest="pastebin", default=None,
|
||||
choices=['failed', 'all'],
|
||||
help="send failed|all info to bpaste.net pastebin service.")
|
||||
action='store', dest="pastebin", default=None,
|
||||
choices=['failed', 'all'],
|
||||
help="send failed|all info to bpaste.net pastebin service.")
|
||||
|
||||
|
||||
@pytest.hookimpl(trylast=True)
|
||||
|
@ -97,4 +97,4 @@ def pytest_terminal_summary(terminalreporter):
|
|||
s = tw.stringio.getvalue()
|
||||
assert len(s)
|
||||
pastebinurl = create_new_paste(s)
|
||||
tr.write_line("%s --> %s" %(msg, pastebinurl))
|
||||
tr.write_line("%s --> %s" % (msg, pastebinurl))
|
||||
|
|
|
@ -25,13 +25,13 @@ from _pytest.assertion.rewrite import AssertionRewritingHook
|
|||
def pytest_addoption(parser):
|
||||
# group = parser.getgroup("pytester", "pytester (self-tests) options")
|
||||
parser.addoption('--lsof',
|
||||
action="store_true", dest="lsof", default=False,
|
||||
help=("run FD checks if lsof is available"))
|
||||
action="store_true", dest="lsof", default=False,
|
||||
help=("run FD checks if lsof is available"))
|
||||
|
||||
parser.addoption('--runpytest', default="inprocess", dest="runpytest",
|
||||
choices=("inprocess", "subprocess", ),
|
||||
help=("run pytest sub runs in tests using an 'inprocess' "
|
||||
"or 'subprocess' (python -m main) method"))
|
||||
choices=("inprocess", "subprocess", ),
|
||||
help=("run pytest sub runs in tests using an 'inprocess' "
|
||||
"or 'subprocess' (python -m main) method"))
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
|
@ -62,7 +62,7 @@ class LsofFdLeakChecker(object):
|
|||
def _parse_lsof_output(self, out):
|
||||
def isopen(line):
|
||||
return line.startswith('f') and ("deleted" not in line and
|
||||
'mem' not in line and "txt" not in line and 'cwd' not in line)
|
||||
'mem' not in line and "txt" not in line and 'cwd' not in line)
|
||||
|
||||
open_files = []
|
||||
|
||||
|
@ -122,6 +122,7 @@ winpymap = {
|
|||
'python3.5': r'C:\Python35\python.exe',
|
||||
}
|
||||
|
||||
|
||||
def getexecutable(name, cache={}):
|
||||
try:
|
||||
return cache[name]
|
||||
|
@ -130,19 +131,20 @@ def getexecutable(name, cache={}):
|
|||
if executable:
|
||||
import subprocess
|
||||
popen = subprocess.Popen([str(executable), "--version"],
|
||||
universal_newlines=True, stderr=subprocess.PIPE)
|
||||
universal_newlines=True, stderr=subprocess.PIPE)
|
||||
out, err = popen.communicate()
|
||||
if name == "jython":
|
||||
if not err or "2.5" not in err:
|
||||
executable = None
|
||||
if "2.5.2" in err:
|
||||
executable = None # http://bugs.jython.org/issue1790
|
||||
executable = None # http://bugs.jython.org/issue1790
|
||||
elif popen.returncode != 0:
|
||||
# Handle pyenv's 127.
|
||||
executable = None
|
||||
cache[name] = executable
|
||||
return executable
|
||||
|
||||
|
||||
@pytest.fixture(params=['python2.6', 'python2.7', 'python3.3', "python3.4",
|
||||
'pypy', 'pypy3'])
|
||||
def anypython(request):
|
||||
|
@ -159,6 +161,8 @@ def anypython(request):
|
|||
return executable
|
||||
|
||||
# used at least by pytest-xdist plugin
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def _pytest(request):
|
||||
""" Return a helper which offers a gethookrecorder(hook)
|
||||
|
@ -167,6 +171,7 @@ def _pytest(request):
|
|||
"""
|
||||
return PytestArg(request)
|
||||
|
||||
|
||||
class PytestArg:
|
||||
def __init__(self, request):
|
||||
self.request = request
|
||||
|
@ -190,7 +195,7 @@ class ParsedCall:
|
|||
def __repr__(self):
|
||||
d = self.__dict__.copy()
|
||||
del d['_name']
|
||||
return "<ParsedCall %r(**%r)>" %(self._name, d)
|
||||
return "<ParsedCall %r(**%r)>" % (self._name, d)
|
||||
|
||||
|
||||
class HookRecorder:
|
||||
|
@ -264,7 +269,7 @@ class HookRecorder:
|
|||
return [x.report for x in self.getcalls(names)]
|
||||
|
||||
def matchreport(self, inamepart="",
|
||||
names="pytest_runtest_logreport pytest_collectreport", when=None):
|
||||
names="pytest_runtest_logreport pytest_collectreport", when=None):
|
||||
""" return a testreport whose dotted import path matches """
|
||||
l = []
|
||||
for rep in self.getreports(names=names):
|
||||
|
@ -283,7 +288,7 @@ class HookRecorder:
|
|||
"no test reports at all!" % (inamepart,))
|
||||
if len(l) > 1:
|
||||
raise ValueError(
|
||||
"found 2 or more testreports matching %r: %s" %(inamepart, l))
|
||||
"found 2 or more testreports matching %r: %s" % (inamepart, l))
|
||||
return l[0]
|
||||
|
||||
def getfailures(self,
|
||||
|
@ -298,7 +303,7 @@ class HookRecorder:
|
|||
skipped = []
|
||||
failed = []
|
||||
for rep in self.getreports(
|
||||
"pytest_collectreport pytest_runtest_logreport"):
|
||||
"pytest_collectreport pytest_runtest_logreport"):
|
||||
if rep.passed:
|
||||
if getattr(rep, "when", None) == "call":
|
||||
passed.append(rep)
|
||||
|
@ -337,6 +342,8 @@ def testdir(request, tmpdir_factory):
|
|||
|
||||
|
||||
rex_outcome = re.compile(r"(\d+) ([\w-]+)")
|
||||
|
||||
|
||||
class RunResult:
|
||||
"""The result of running a command.
|
||||
|
||||
|
@ -352,6 +359,7 @@ class RunResult:
|
|||
:duration: Duration in seconds.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, ret, outlines, errlines, duration):
|
||||
self.ret = ret
|
||||
self.outlines = outlines
|
||||
|
@ -382,7 +390,6 @@ class RunResult:
|
|||
assert failed == d.get("failed", 0)
|
||||
|
||||
|
||||
|
||||
class Testdir:
|
||||
"""Temporary test directory with tools to test/run pytest itself.
|
||||
|
||||
|
@ -406,7 +413,7 @@ class Testdir:
|
|||
|
||||
def __init__(self, request, tmpdir_factory):
|
||||
self.request = request
|
||||
self._mod_collections = WeakKeyDictionary()
|
||||
self._mod_collections = WeakKeyDictionary()
|
||||
# XXX remove duplication with tmpdir plugin
|
||||
basetmp = tmpdir_factory.ensuretemp("testdir")
|
||||
name = request.function.__name__
|
||||
|
@ -420,7 +427,7 @@ class Testdir:
|
|||
self.plugins = []
|
||||
self._savesyspath = (list(sys.path), list(sys.meta_path))
|
||||
self._savemodulekeys = set(sys.modules)
|
||||
self.chdir() # always chdir
|
||||
self.chdir() # always chdir
|
||||
self.request.addfinalizer(self.finalize)
|
||||
method = self.request.config.getoption("--runpytest")
|
||||
if method == "inprocess":
|
||||
|
@ -495,8 +502,8 @@ class Testdir:
|
|||
|
||||
source_unicode = "\n".join([my_totext(line) for line in source.lines])
|
||||
source = py.builtin._totext(source_unicode)
|
||||
content = source.strip().encode(encoding) # + "\n"
|
||||
#content = content.rstrip() + "\n"
|
||||
content = source.strip().encode(encoding) # + "\n"
|
||||
# content = content.rstrip() + "\n"
|
||||
p.write(content, "wb")
|
||||
if ret is None:
|
||||
ret = p
|
||||
|
@ -581,6 +588,7 @@ class Testdir:
|
|||
return p
|
||||
|
||||
Session = Session
|
||||
|
||||
def getnode(self, config, arg):
|
||||
"""Return the collection node of a file.
|
||||
|
||||
|
@ -763,7 +771,7 @@ class Testdir:
|
|||
|
||||
res = RunResult(reprec.ret,
|
||||
out.split("\n"), err.split("\n"),
|
||||
time.time()-now)
|
||||
time.time() - now)
|
||||
res.reprec = reprec
|
||||
return res
|
||||
|
||||
|
@ -779,11 +787,11 @@ class Testdir:
|
|||
args = [str(x) for x in args]
|
||||
for x in args:
|
||||
if str(x).startswith('--basetemp'):
|
||||
#print ("basedtemp exists: %s" %(args,))
|
||||
# print("basedtemp exists: %s" %(args,))
|
||||
break
|
||||
else:
|
||||
args.append("--basetemp=%s" % self.tmpdir.dirpath('basetemp'))
|
||||
#print ("added basetemp: %s" %(args,))
|
||||
# print("added basetemp: %s" %(args,))
|
||||
return args
|
||||
|
||||
def parseconfig(self, *args):
|
||||
|
@ -821,7 +829,7 @@ class Testdir:
|
|||
self.request.addfinalizer(config._ensure_unconfigure)
|
||||
return config
|
||||
|
||||
def getitem(self, source, funcname="test_func"):
|
||||
def getitem(self, source, funcname="test_func"):
|
||||
"""Return the test item for a test function.
|
||||
|
||||
This writes the source to a python file and runs pytest's
|
||||
|
@ -838,10 +846,10 @@ class Testdir:
|
|||
for item in items:
|
||||
if item.name == funcname:
|
||||
return item
|
||||
assert 0, "%r item not found in module:\n%s\nitems: %s" %(
|
||||
assert 0, "%r item not found in module:\n%s\nitems: %s" % (
|
||||
funcname, source, items)
|
||||
|
||||
def getitems(self, source):
|
||||
def getitems(self, source):
|
||||
"""Return all test items collected from the module.
|
||||
|
||||
This writes the source to a python file and runs pytest's
|
||||
|
@ -852,7 +860,7 @@ class Testdir:
|
|||
modcol = self.getmodulecol(source)
|
||||
return self.genitems([modcol])
|
||||
|
||||
def getmodulecol(self, source, configargs=(), withinit=False):
|
||||
def getmodulecol(self, source, configargs=(), withinit=False):
|
||||
"""Return the module collection node for ``source``.
|
||||
|
||||
This writes ``source`` to a file using :py:meth:`makepyfile`
|
||||
|
@ -871,7 +879,7 @@ class Testdir:
|
|||
kw = {self.request.function.__name__: Source(source).strip()}
|
||||
path = self.makepyfile(**kw)
|
||||
if withinit:
|
||||
self.makepyfile(__init__ = "#")
|
||||
self.makepyfile(__init__="#")
|
||||
self.config = config = self.parseconfigure(path, *configargs)
|
||||
node = self.getnode(config, path)
|
||||
|
||||
|
@ -933,7 +941,7 @@ class Testdir:
|
|||
try:
|
||||
now = time.time()
|
||||
popen = self.popen(cmdargs, stdout=f1, stderr=f2,
|
||||
close_fds=(sys.platform != "win32"))
|
||||
close_fds=(sys.platform != "win32"))
|
||||
ret = popen.wait()
|
||||
finally:
|
||||
f1.close()
|
||||
|
@ -948,7 +956,7 @@ class Testdir:
|
|||
f2.close()
|
||||
self._dump_lines(out, sys.stdout)
|
||||
self._dump_lines(err, sys.stderr)
|
||||
return RunResult(ret, out, err, time.time()-now)
|
||||
return RunResult(ret, out, err, time.time() - now)
|
||||
|
||||
def _dump_lines(self, lines, fp):
|
||||
try:
|
||||
|
@ -960,7 +968,7 @@ class Testdir:
|
|||
def _getpytestargs(self):
|
||||
# we cannot use "(sys.executable,script)"
|
||||
# because on windows the script is e.g. a pytest.exe
|
||||
return (sys.executable, _pytest_fullpath,) # noqa
|
||||
return (sys.executable, _pytest_fullpath,) # noqa
|
||||
|
||||
def runpython(self, script):
|
||||
"""Run a python script using sys.executable as interpreter.
|
||||
|
@ -987,12 +995,12 @@ class Testdir:
|
|||
|
||||
"""
|
||||
p = py.path.local.make_numbered_dir(prefix="runpytest-",
|
||||
keep=None, rootdir=self.tmpdir)
|
||||
keep=None, rootdir=self.tmpdir)
|
||||
args = ('--basetemp=%s' % p, ) + args
|
||||
#for x in args:
|
||||
# for x in args:
|
||||
# if '--confcutdir' in str(x):
|
||||
# break
|
||||
#else:
|
||||
# else:
|
||||
# pass
|
||||
# args = ('--confcutdir=.',) + args
|
||||
plugins = [x for x in self.plugins if isinstance(x, str)]
|
||||
|
@ -1031,12 +1039,13 @@ class Testdir:
|
|||
child.timeout = expect_timeout
|
||||
return child
|
||||
|
||||
|
||||
def getdecoded(out):
|
||||
try:
|
||||
return out.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
|
||||
py.io.saferepr(out),)
|
||||
try:
|
||||
return out.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
|
||||
py.io.saferepr(out),)
|
||||
|
||||
|
||||
class LineComp:
|
||||
|
@ -1066,7 +1075,7 @@ class LineMatcher:
|
|||
|
||||
"""
|
||||
|
||||
def __init__(self, lines):
|
||||
def __init__(self, lines):
|
||||
self.lines = lines
|
||||
self._log_output = []
|
||||
|
||||
|
@ -1105,7 +1114,7 @@ class LineMatcher:
|
|||
"""
|
||||
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):
|
||||
|
|
|
@ -49,7 +49,6 @@ def filter_traceback(entry):
|
|||
return p != cutdir1 and not p.relto(cutdir2) and not p.relto(cutdir3)
|
||||
|
||||
|
||||
|
||||
def pyobj_property(name):
|
||||
def get(self):
|
||||
node = self.getparent(getattr(__import__('pytest'), name))
|
||||
|
@ -63,8 +62,8 @@ def pyobj_property(name):
|
|||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
group.addoption('--fixtures', '--funcargs',
|
||||
action="store_true", dest="showfixtures", default=False,
|
||||
help="show available fixtures, sorted by plugin appearance")
|
||||
action="store_true", dest="showfixtures", default=False,
|
||||
help="show available fixtures, sorted by plugin appearance")
|
||||
group.addoption(
|
||||
'--fixtures-per-test',
|
||||
action="store_true",
|
||||
|
@ -73,20 +72,20 @@ def pytest_addoption(parser):
|
|||
help="show fixtures per test",
|
||||
)
|
||||
parser.addini("usefixtures", type="args", default=[],
|
||||
help="list of default fixtures to be used with this project")
|
||||
help="list of default fixtures to be used with this project")
|
||||
parser.addini("python_files", type="args",
|
||||
default=['test_*.py', '*_test.py'],
|
||||
help="glob-style file patterns for Python test module discovery")
|
||||
parser.addini("python_classes", type="args", default=["Test",],
|
||||
help="prefixes or glob names for Python test class discovery")
|
||||
parser.addini("python_functions", type="args", default=["test",],
|
||||
help="prefixes or glob names for Python test function and "
|
||||
"method discovery")
|
||||
default=['test_*.py', '*_test.py'],
|
||||
help="glob-style file patterns for Python test module discovery")
|
||||
parser.addini("python_classes", type="args", default=["Test", ],
|
||||
help="prefixes or glob names for Python test class discovery")
|
||||
parser.addini("python_functions", type="args", default=["test", ],
|
||||
help="prefixes or glob names for Python test function and "
|
||||
"method discovery")
|
||||
|
||||
group.addoption("--import-mode", default="prepend",
|
||||
choices=["prepend", "append"], dest="importmode",
|
||||
help="prepend/append to sys.path when importing test modules, "
|
||||
"default is to prepend.")
|
||||
choices=["prepend", "append"], dest="importmode",
|
||||
help="prepend/append to sys.path when importing test modules, "
|
||||
"default is to prepend.")
|
||||
|
||||
|
||||
def pytest_cmdline_main(config):
|
||||
|
@ -113,21 +112,22 @@ def pytest_generate_tests(metafunc):
|
|||
for marker in markers:
|
||||
metafunc.parametrize(*marker.args, **marker.kwargs)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
config.addinivalue_line("markers",
|
||||
"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."
|
||||
)
|
||||
"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."
|
||||
)
|
||||
config.addinivalue_line("markers",
|
||||
"usefixtures(fixturename1, fixturename2, ...): mark tests as needing "
|
||||
"all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures "
|
||||
)
|
||||
"usefixtures(fixturename1, fixturename2, ...): mark tests as needing "
|
||||
"all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures "
|
||||
)
|
||||
|
||||
|
||||
@hookimpl(trylast=True)
|
||||
|
@ -152,13 +152,15 @@ def pytest_collect_file(path, parent):
|
|||
if path.fnmatch(pat):
|
||||
break
|
||||
else:
|
||||
return
|
||||
return
|
||||
ihook = parent.session.gethookproxy(path)
|
||||
return ihook.pytest_pycollect_makemodule(path=path, parent=parent)
|
||||
|
||||
|
||||
def pytest_pycollect_makemodule(path, parent):
|
||||
return Module(path, parent)
|
||||
|
||||
|
||||
@hookimpl(hookwrapper=True)
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
outcome = yield
|
||||
|
@ -177,9 +179,8 @@ def pytest_pycollect_makeitem(collector, name, obj):
|
|||
# or a funtools.wrapped.
|
||||
# We musn't if it's been wrapped with mock.patch (python 2 only)
|
||||
if not (isfunction(obj) or isfunction(get_real_func(obj))):
|
||||
collector.warn(code="C2", message=
|
||||
"cannot collect %r because it is not a function."
|
||||
% name, )
|
||||
collector.warn(code="C2", message="cannot collect %r because it is not a function."
|
||||
% name, )
|
||||
elif getattr(obj, "__test__", True):
|
||||
if is_generator(obj):
|
||||
res = Generator(name, parent=collector)
|
||||
|
@ -187,16 +188,17 @@ def pytest_pycollect_makeitem(collector, name, obj):
|
|||
res = list(collector._genfunctions(name, obj))
|
||||
outcome.force_result(res)
|
||||
|
||||
|
||||
def pytest_make_parametrize_id(config, val, argname=None):
|
||||
return None
|
||||
|
||||
|
||||
|
||||
class PyobjContext(object):
|
||||
module = pyobj_property("Module")
|
||||
cls = pyobj_property("Class")
|
||||
instance = pyobj_property("Instance")
|
||||
|
||||
|
||||
class PyobjMixin(PyobjContext):
|
||||
def obj():
|
||||
def fget(self):
|
||||
|
@ -254,6 +256,7 @@ class PyobjMixin(PyobjContext):
|
|||
assert isinstance(lineno, int)
|
||||
return fspath, lineno, modpath
|
||||
|
||||
|
||||
class PyCollector(PyobjMixin, main.Collector):
|
||||
|
||||
def funcnamefilter(self, name):
|
||||
|
@ -322,7 +325,7 @@ class PyCollector(PyobjMixin, main.Collector):
|
|||
return l
|
||||
|
||||
def makeitem(self, name, obj):
|
||||
#assert self.ihook.fspath == self.fspath, self
|
||||
# assert self.ihook.fspath == self.fspath, self
|
||||
return self.ihook.pytest_pycollect_makeitem(
|
||||
collector=self, name=name, obj=obj)
|
||||
|
||||
|
@ -358,7 +361,7 @@ class PyCollector(PyobjMixin, main.Collector):
|
|||
yield Function(name=subname, parent=self,
|
||||
callspec=callspec, callobj=funcobj,
|
||||
fixtureinfo=fixtureinfo,
|
||||
keywords={callspec.id:True},
|
||||
keywords={callspec.id: True},
|
||||
originalname=name,
|
||||
)
|
||||
|
||||
|
@ -420,7 +423,7 @@ class Module(main.File, PyCollector):
|
|||
" %s\n"
|
||||
"HINT: remove __pycache__ / .pyc files and/or use a "
|
||||
"unique basename for your test file modules"
|
||||
% e.args
|
||||
% e.args
|
||||
)
|
||||
except ImportError:
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
|
@ -492,12 +495,13 @@ def _get_xunit_func(obj, name):
|
|||
|
||||
class Class(PyCollector):
|
||||
""" Collector for test methods. """
|
||||
|
||||
def collect(self):
|
||||
if not safe_getattr(self.obj, "__test__", True):
|
||||
return []
|
||||
if hasinit(self.obj):
|
||||
self.warn("C1", "cannot collect test class %r because it has a "
|
||||
"__init__ constructor" % self.obj.__name__)
|
||||
"__init__ constructor" % self.obj.__name__)
|
||||
return []
|
||||
elif hasnew(self.obj):
|
||||
self.warn("C1", "cannot collect test class %r because it has a "
|
||||
|
@ -518,6 +522,7 @@ class Class(PyCollector):
|
|||
fin_class = getattr(fin_class, '__func__', fin_class)
|
||||
self.addfinalizer(lambda: fin_class(self.obj))
|
||||
|
||||
|
||||
class Instance(PyCollector):
|
||||
def _getobj(self):
|
||||
return self.parent.obj()
|
||||
|
@ -530,6 +535,7 @@ class Instance(PyCollector):
|
|||
self.obj = self._getobj()
|
||||
return self.obj
|
||||
|
||||
|
||||
class FunctionMixin(PyobjMixin):
|
||||
""" mixin for the code common to Function and Generator.
|
||||
"""
|
||||
|
@ -565,7 +571,7 @@ class FunctionMixin(PyobjMixin):
|
|||
if ntraceback == traceback:
|
||||
ntraceback = ntraceback.cut(path=path)
|
||||
if ntraceback == traceback:
|
||||
#ntraceback = ntraceback.cut(excludepath=cutdir2)
|
||||
# ntraceback = ntraceback.cut(excludepath=cutdir2)
|
||||
ntraceback = ntraceback.filter(filter_traceback)
|
||||
if not ntraceback:
|
||||
ntraceback = traceback
|
||||
|
@ -583,7 +589,7 @@ class FunctionMixin(PyobjMixin):
|
|||
if not excinfo.value.pytrace:
|
||||
return py._builtin._totext(excinfo.value)
|
||||
return super(FunctionMixin, self)._repr_failure_py(excinfo,
|
||||
style=style)
|
||||
style=style)
|
||||
|
||||
def repr_failure(self, excinfo, outerr=None):
|
||||
assert outerr is None, "XXX outerr usage is deprecated"
|
||||
|
@ -607,13 +613,13 @@ class Generator(FunctionMixin, PyCollector):
|
|||
for i, x in enumerate(self.obj()):
|
||||
name, call, args = self.getcallargs(x)
|
||||
if not callable(call):
|
||||
raise TypeError("%r yielded non callable test %r" %(self.obj, call,))
|
||||
raise TypeError("%r yielded non callable test %r" % (self.obj, call,))
|
||||
if name is None:
|
||||
name = "[%d]" % i
|
||||
else:
|
||||
name = "['%s']" % name
|
||||
if name in seen:
|
||||
raise ValueError("%r generated tests with non-unique name %r" %(self, name))
|
||||
raise ValueError("%r generated tests with non-unique name %r" % (self, name))
|
||||
seen[name] = True
|
||||
l.append(self.Function(name, self, args=args, callobj=call))
|
||||
self.warn('C1', deprecated.YIELD_TESTS)
|
||||
|
@ -672,7 +678,7 @@ class CallSpec2(object):
|
|||
|
||||
def _checkargnotcontained(self, arg):
|
||||
if arg in self.params or arg in self.funcargs:
|
||||
raise ValueError("duplicate %r" %(arg,))
|
||||
raise ValueError("duplicate %r" % (arg,))
|
||||
|
||||
def getparam(self, name):
|
||||
try:
|
||||
|
@ -688,7 +694,7 @@ class CallSpec2(object):
|
|||
|
||||
def setmulti(self, valtypes, argnames, valset, id, keywords, scopenum,
|
||||
param_index):
|
||||
for arg,val in zip(argnames, valset):
|
||||
for arg, val in zip(argnames, valset):
|
||||
self._checkargnotcontained(arg)
|
||||
valtype_for_arg = valtypes[arg]
|
||||
getattr(self, valtype_for_arg)[arg] = val
|
||||
|
@ -717,6 +723,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
test configuration or values specified in the class or module where a
|
||||
test function is defined.
|
||||
"""
|
||||
|
||||
def __init__(self, function, fixtureinfo, config, cls=None, module=None):
|
||||
#: access to the :class:`_pytest.config.Config` object for the test session
|
||||
self.config = config
|
||||
|
@ -738,7 +745,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
self._arg2fixturedefs = fixtureinfo.name2fixturedefs
|
||||
|
||||
def parametrize(self, argnames, argvalues, indirect=False, ids=None,
|
||||
scope=None):
|
||||
scope=None):
|
||||
""" Add new invocations to the underlying test function using the list
|
||||
of argvalues for the given argnames. Parametrization is performed
|
||||
during the collection phase. If you need to setup expensive resources
|
||||
|
@ -793,7 +800,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
if not parameters:
|
||||
fs, lineno = getfslineno(self.function)
|
||||
reason = "got empty parameter set %r, function %s at %s:%d" % (
|
||||
argnames, self.function.__name__, fs, lineno)
|
||||
argnames, self.function.__name__, fs, lineno)
|
||||
mark = MARK_GEN.skip(reason=reason)
|
||||
parameters.append(ParameterSet(
|
||||
values=(NOTSET,) * len(argnames),
|
||||
|
@ -814,7 +821,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
name = 'fixture' if indirect else 'argument'
|
||||
raise ValueError(
|
||||
"%r uses no %s %r" % (
|
||||
self.function, name, arg))
|
||||
self.function, name, arg))
|
||||
|
||||
if indirect is True:
|
||||
valtypes = dict.fromkeys(argnames, "params")
|
||||
|
@ -905,7 +912,7 @@ 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
|
||||
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()]
|
||||
|
@ -948,7 +955,7 @@ def _idval(val, argname, idx, idfn, config=None):
|
|||
return str(val)
|
||||
elif isclass(val) and hasattr(val, '__name__'):
|
||||
return val.__name__
|
||||
return str(argname)+str(idx)
|
||||
return str(argname) + str(idx)
|
||||
|
||||
|
||||
def _idvalset(idx, parameterset, argnames, idfn, ids, config=None):
|
||||
|
@ -1071,12 +1078,12 @@ def _showfixtures_main(config, session):
|
|||
if currentmodule != module:
|
||||
if not module.startswith("_pytest."):
|
||||
tw.line()
|
||||
tw.sep("-", "fixtures defined from %s" %(module,))
|
||||
tw.sep("-", "fixtures defined from %s" % (module,))
|
||||
currentmodule = module
|
||||
if verbose <= 0 and argname[0] == "_":
|
||||
continue
|
||||
if verbose > 0:
|
||||
funcargspec = "%s -- %s" %(argname, bestrel,)
|
||||
funcargspec = "%s -- %s" % (argname, bestrel,)
|
||||
else:
|
||||
funcargspec = argname
|
||||
tw.line(funcargspec, green=True)
|
||||
|
@ -1085,8 +1092,8 @@ def _showfixtures_main(config, session):
|
|||
if doc:
|
||||
write_docstring(tw, doc)
|
||||
else:
|
||||
tw.line(" %s: no docstring available" %(loc,),
|
||||
red=True)
|
||||
tw.line(" %s: no docstring available" % (loc,),
|
||||
red=True)
|
||||
|
||||
|
||||
def write_docstring(tw, doc):
|
||||
|
@ -1228,7 +1235,7 @@ def raises(expected_exception, *args, **kwargs):
|
|||
frame = sys._getframe(1)
|
||||
loc = frame.f_locals.copy()
|
||||
loc.update(kwargs)
|
||||
#print "raises frame scope: %r" % frame.f_locals
|
||||
# print "raises frame scope: %r" % frame.f_locals
|
||||
try:
|
||||
code = _pytest._code.Source(code).compile()
|
||||
py.builtin.exec_(code, frame.f_globals, loc)
|
||||
|
@ -1422,7 +1429,10 @@ class approx(object):
|
|||
# or a sequence of numbers, return a list of ApproxNotIterable objects
|
||||
# that can be compared against.
|
||||
from collections import Iterable
|
||||
approx_non_iter = lambda x: ApproxNonIterable(x, self.rel, self.abs)
|
||||
|
||||
def approx_non_iter(x):
|
||||
return ApproxNonIterable(x, self.rel, self.abs)
|
||||
|
||||
if isinstance(self._expected, Iterable):
|
||||
return [approx_non_iter(x) for x in self._expected]
|
||||
else:
|
||||
|
@ -1496,7 +1506,8 @@ class ApproxNonIterable(object):
|
|||
|
||||
@property
|
||||
def tolerance(self):
|
||||
set_default = lambda x, default: x if x is not None else default
|
||||
def set_default(x, default):
|
||||
return x if x is not None else default
|
||||
|
||||
# Figure out what the absolute tolerance should be. ``self.abs`` is
|
||||
# either None or a value specified by the user.
|
||||
|
@ -1538,6 +1549,7 @@ class Function(FunctionMixin, main.Item, fixtures.FuncargnamesCompatAttr):
|
|||
Python test function.
|
||||
"""
|
||||
_genid = None
|
||||
|
||||
def __init__(self, name, parent, args=None, config=None,
|
||||
callspec=None, callobj=NOTSET, keywords=None, session=None,
|
||||
fixtureinfo=None, originalname=None):
|
||||
|
@ -1589,7 +1601,7 @@ class Function(FunctionMixin, main.Item, fixtures.FuncargnamesCompatAttr):
|
|||
|
||||
def _getobj(self):
|
||||
name = self.name
|
||||
i = name.find("[") # parametrization
|
||||
i = name.find("[") # parametrization
|
||||
if i != -1:
|
||||
name = name[:i]
|
||||
return getattr(self.parent.obj, name)
|
||||
|
|
|
@ -200,5 +200,5 @@ class WarningsChecker(WarningsRecorder):
|
|||
from _pytest.runner import fail
|
||||
fail("DID NOT WARN. No warnings of type {0} was emitted. "
|
||||
"The list of emitted warnings is: {1}.".format(
|
||||
self.expected_warning,
|
||||
[each.message for each in self]))
|
||||
self.expected_warning,
|
||||
[each.message for each in self]))
|
||||
|
|
|
@ -6,11 +6,13 @@ from __future__ import absolute_import, division, print_function
|
|||
import py
|
||||
import os
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("terminal reporting", "resultlog plugin options")
|
||||
group.addoption('--resultlog', '--result-log', action="store",
|
||||
metavar="path", default=None,
|
||||
help="DEPRECATED path for machine-readable result log.")
|
||||
metavar="path", default=None,
|
||||
help="DEPRECATED path for machine-readable result log.")
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
resultlog = config.option.resultlog
|
||||
|
@ -19,13 +21,14 @@ def pytest_configure(config):
|
|||
dirname = os.path.dirname(os.path.abspath(resultlog))
|
||||
if not os.path.isdir(dirname):
|
||||
os.makedirs(dirname)
|
||||
logfile = open(resultlog, 'w', 1) # line buffered
|
||||
logfile = open(resultlog, 'w', 1) # line buffered
|
||||
config._resultlog = ResultLog(config, logfile)
|
||||
config.pluginmanager.register(config._resultlog)
|
||||
|
||||
from _pytest.deprecated import RESULT_LOG
|
||||
config.warn('C1', RESULT_LOG)
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
resultlog = getattr(config, '_resultlog', None)
|
||||
if resultlog:
|
||||
|
@ -33,6 +36,7 @@ def pytest_unconfigure(config):
|
|||
del config._resultlog
|
||||
config.pluginmanager.unregister(resultlog)
|
||||
|
||||
|
||||
def generic_path(item):
|
||||
chain = item.listchain()
|
||||
gpath = [chain[0].name]
|
||||
|
@ -56,10 +60,11 @@ def generic_path(item):
|
|||
fspath = newfspath
|
||||
return ''.join(gpath)
|
||||
|
||||
|
||||
class ResultLog(object):
|
||||
def __init__(self, config, logfile):
|
||||
self.config = config
|
||||
self.logfile = logfile # preferably line buffered
|
||||
self.logfile = logfile # preferably line buffered
|
||||
|
||||
def write_log_entry(self, testpath, lettercode, longrepr):
|
||||
print("%s %s" % (lettercode, testpath), file=self.logfile)
|
||||
|
|
|
@ -9,15 +9,15 @@ import py
|
|||
from _pytest._code.code import TerminalRepr, ExceptionInfo
|
||||
|
||||
|
||||
|
||||
#
|
||||
# pytest plugin hooks
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("terminal reporting", "reporting", after="general")
|
||||
group.addoption('--durations',
|
||||
action="store", type=int, default=None, metavar="N",
|
||||
help="show N slowest setup/test durations (N=0 for all)."),
|
||||
action="store", type=int, default=None, metavar="N",
|
||||
help="show N slowest setup/test durations (N=0 for all)."),
|
||||
|
||||
|
||||
def pytest_terminal_summary(terminalreporter):
|
||||
durations = terminalreporter.config.option.durations
|
||||
|
@ -42,17 +42,22 @@ def pytest_terminal_summary(terminalreporter):
|
|||
for rep in dlist:
|
||||
nodeid = rep.nodeid.replace("::()::", "::")
|
||||
tr.write_line("%02.2fs %-8s %s" %
|
||||
(rep.duration, rep.when, nodeid))
|
||||
(rep.duration, rep.when, nodeid))
|
||||
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
session._setupstate = SetupState()
|
||||
|
||||
|
||||
def pytest_sessionfinish(session):
|
||||
session._setupstate.teardown_all()
|
||||
|
||||
|
||||
class NodeInfo:
|
||||
def __init__(self, location):
|
||||
self.location = location
|
||||
|
||||
|
||||
def pytest_runtest_protocol(item, nextitem):
|
||||
item.ihook.pytest_runtest_logstart(
|
||||
nodeid=item.nodeid, location=item.location,
|
||||
|
@ -60,6 +65,7 @@ def pytest_runtest_protocol(item, nextitem):
|
|||
runtestprotocol(item, nextitem=nextitem)
|
||||
return True
|
||||
|
||||
|
||||
def runtestprotocol(item, log=True, nextitem=None):
|
||||
hasrequest = hasattr(item, "_request")
|
||||
if hasrequest and not item._request:
|
||||
|
@ -72,7 +78,7 @@ def runtestprotocol(item, log=True, nextitem=None):
|
|||
if not item.config.option.setuponly:
|
||||
reports.append(call_and_report(item, "call", log))
|
||||
reports.append(call_and_report(item, "teardown", log,
|
||||
nextitem=nextitem))
|
||||
nextitem=nextitem))
|
||||
# after all teardown hooks have been called
|
||||
# want funcargs and request info to go away
|
||||
if hasrequest:
|
||||
|
@ -80,6 +86,7 @@ def runtestprotocol(item, log=True, nextitem=None):
|
|||
item.funcargs = None
|
||||
return reports
|
||||
|
||||
|
||||
def show_test_item(item):
|
||||
"""Show test function, parameters and the fixtures of the test item."""
|
||||
tw = item.config.get_terminal_writer()
|
||||
|
@ -90,9 +97,11 @@ def show_test_item(item):
|
|||
if used_fixtures:
|
||||
tw.write(' (fixtures used: {0})'.format(', '.join(used_fixtures)))
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
item.session._setupstate.prepare(item)
|
||||
|
||||
|
||||
def pytest_runtest_call(item):
|
||||
try:
|
||||
item.runtest()
|
||||
|
@ -106,9 +115,11 @@ def pytest_runtest_call(item):
|
|||
del tb # Get rid of it in this namespace
|
||||
raise
|
||||
|
||||
|
||||
def pytest_runtest_teardown(item, nextitem):
|
||||
item.session._setupstate.teardown_exact(item, nextitem)
|
||||
|
||||
|
||||
def pytest_report_teststatus(report):
|
||||
if report.when in ("setup", "teardown"):
|
||||
if report.failed:
|
||||
|
@ -133,21 +144,25 @@ def call_and_report(item, when, log=True, **kwds):
|
|||
hook.pytest_exception_interact(node=item, call=call, report=report)
|
||||
return report
|
||||
|
||||
|
||||
def check_interactive_exception(call, report):
|
||||
return call.excinfo and not (
|
||||
hasattr(report, "wasxfail") or
|
||||
call.excinfo.errisinstance(skip.Exception) or
|
||||
call.excinfo.errisinstance(bdb.BdbQuit))
|
||||
hasattr(report, "wasxfail") or
|
||||
call.excinfo.errisinstance(skip.Exception) or
|
||||
call.excinfo.errisinstance(bdb.BdbQuit))
|
||||
|
||||
|
||||
def call_runtest_hook(item, when, **kwds):
|
||||
hookname = "pytest_runtest_" + when
|
||||
ihook = getattr(item.ihook, hookname)
|
||||
return CallInfo(lambda: ihook(item=item, **kwds), when=when)
|
||||
|
||||
|
||||
class CallInfo:
|
||||
""" Result/Exception info a function invocation. """
|
||||
#: None or ExceptionInfo object.
|
||||
excinfo = None
|
||||
|
||||
def __init__(self, func, when):
|
||||
#: context of invocation: one of "setup", "call",
|
||||
#: "teardown", "memocollect"
|
||||
|
@ -169,6 +184,7 @@ class CallInfo:
|
|||
status = "result: %r" % (self.result,)
|
||||
return "<CallInfo when=%r %s>" % (self.when, status)
|
||||
|
||||
|
||||
def getslaveinfoline(node):
|
||||
try:
|
||||
return node._slaveinfocache
|
||||
|
@ -179,6 +195,7 @@ def getslaveinfoline(node):
|
|||
d['id'], d['sysplatform'], ver, d['executable'])
|
||||
return s
|
||||
|
||||
|
||||
class BaseReport(object):
|
||||
|
||||
def __init__(self, **kw):
|
||||
|
@ -243,10 +260,11 @@ class BaseReport(object):
|
|||
def fspath(self):
|
||||
return self.nodeid.split("::")[0]
|
||||
|
||||
|
||||
def pytest_runtest_makereport(item, call):
|
||||
when = call.when
|
||||
duration = call.stop-call.start
|
||||
keywords = dict([(x,1) for x in item.keywords])
|
||||
duration = call.stop - call.start
|
||||
keywords = dict([(x, 1) for x in item.keywords])
|
||||
excinfo = call.excinfo
|
||||
sections = []
|
||||
if not call.excinfo:
|
||||
|
@ -264,19 +282,21 @@ def pytest_runtest_makereport(item, call):
|
|||
outcome = "failed"
|
||||
if call.when == "call":
|
||||
longrepr = item.repr_failure(excinfo)
|
||||
else: # exception in setup or teardown
|
||||
else: # exception in setup or teardown
|
||||
longrepr = item._repr_failure_py(excinfo,
|
||||
style=item.config.option.tbstyle)
|
||||
style=item.config.option.tbstyle)
|
||||
for rwhen, key, content in item._report_sections:
|
||||
sections.append(("Captured %s %s" %(key, rwhen), content))
|
||||
sections.append(("Captured %s %s" % (key, rwhen), content))
|
||||
return TestReport(item.nodeid, item.location,
|
||||
keywords, outcome, longrepr, when,
|
||||
sections, duration)
|
||||
|
||||
|
||||
class TestReport(BaseReport):
|
||||
""" Basic test report object (also used for setup and teardown calls if
|
||||
they fail).
|
||||
"""
|
||||
|
||||
def __init__(self, nodeid, location, keywords, outcome,
|
||||
longrepr, when, sections=(), duration=0, **extra):
|
||||
#: normalized collection node id
|
||||
|
@ -315,14 +335,17 @@ class TestReport(BaseReport):
|
|||
return "<TestReport %r when=%r outcome=%r>" % (
|
||||
self.nodeid, self.when, self.outcome)
|
||||
|
||||
|
||||
class TeardownErrorReport(BaseReport):
|
||||
outcome = "failed"
|
||||
when = "teardown"
|
||||
|
||||
def __init__(self, longrepr, **extra):
|
||||
self.longrepr = longrepr
|
||||
self.sections = []
|
||||
self.__dict__.update(extra)
|
||||
|
||||
|
||||
def pytest_make_collect_report(collector):
|
||||
call = CallInfo(
|
||||
lambda: list(collector.collect()),
|
||||
|
@ -344,7 +367,7 @@ def pytest_make_collect_report(collector):
|
|||
errorinfo = CollectErrorRepr(errorinfo)
|
||||
longrepr = errorinfo
|
||||
rep = CollectReport(collector.nodeid, outcome, longrepr,
|
||||
getattr(call, 'result', None))
|
||||
getattr(call, 'result', None))
|
||||
rep.call = call # see collect_one_node
|
||||
return rep
|
||||
|
||||
|
@ -365,16 +388,20 @@ class CollectReport(BaseReport):
|
|||
|
||||
def __repr__(self):
|
||||
return "<CollectReport %r lenresult=%s outcome=%r>" % (
|
||||
self.nodeid, len(self.result), self.outcome)
|
||||
self.nodeid, len(self.result), self.outcome)
|
||||
|
||||
|
||||
class CollectErrorRepr(TerminalRepr):
|
||||
def __init__(self, msg):
|
||||
self.longrepr = msg
|
||||
|
||||
def toterminal(self, out):
|
||||
out.line(self.longrepr, red=True)
|
||||
|
||||
|
||||
class SetupState(object):
|
||||
""" shared state for setting up/tearing down test items or collectors. """
|
||||
|
||||
def __init__(self):
|
||||
self.stack = []
|
||||
self._finalizers = {}
|
||||
|
@ -386,7 +413,7 @@ class SetupState(object):
|
|||
"""
|
||||
assert colitem and not isinstance(colitem, tuple)
|
||||
assert py.builtin.callable(finalizer)
|
||||
#assert colitem in self.stack # some unit tests don't setup stack :/
|
||||
# assert colitem in self.stack # some unit tests don't setup stack :/
|
||||
self._finalizers.setdefault(colitem, []).append(finalizer)
|
||||
|
||||
def _pop_and_teardown(self):
|
||||
|
@ -414,7 +441,7 @@ class SetupState(object):
|
|||
colitem.teardown()
|
||||
for colitem in self._finalizers:
|
||||
assert colitem is None or colitem in self.stack \
|
||||
or isinstance(colitem, tuple)
|
||||
or isinstance(colitem, tuple)
|
||||
|
||||
def teardown_all(self):
|
||||
while self.stack:
|
||||
|
@ -451,6 +478,7 @@ class SetupState(object):
|
|||
col._prepare_exc = sys.exc_info()
|
||||
raise
|
||||
|
||||
|
||||
def collect_one_node(collector):
|
||||
ihook = collector.ihook
|
||||
ihook.pytest_collectstart(collector=collector)
|
||||
|
@ -469,6 +497,7 @@ class OutcomeException(Exception):
|
|||
""" OutcomeException and its subclass instances indicate and
|
||||
contain info about test and collection outcomes.
|
||||
"""
|
||||
|
||||
def __init__(self, msg=None, pytrace=True):
|
||||
Exception.__init__(self, msg)
|
||||
self.msg = msg
|
||||
|
@ -480,9 +509,10 @@ class OutcomeException(Exception):
|
|||
if isinstance(val, bytes):
|
||||
val = py._builtin._totext(val, errors='replace')
|
||||
return val
|
||||
return "<%s instance>" %(self.__class__.__name__,)
|
||||
return "<%s instance>" % (self.__class__.__name__,)
|
||||
__str__ = __repr__
|
||||
|
||||
|
||||
class Skipped(OutcomeException):
|
||||
# XXX hackish: on 3k we fake to live in the builtins
|
||||
# in order to have Skipped exception printing shorter/nicer
|
||||
|
@ -500,12 +530,14 @@ class Failed(OutcomeException):
|
|||
|
||||
class Exit(KeyboardInterrupt):
|
||||
""" raised for immediate program exits (no tracebacks/summaries)"""
|
||||
|
||||
def __init__(self, msg="unknown reason"):
|
||||
self.msg = msg
|
||||
KeyboardInterrupt.__init__(self, msg)
|
||||
|
||||
# exposed helper methods
|
||||
|
||||
|
||||
def exit(msg):
|
||||
""" exit testing process as if KeyboardInterrupt was triggered. """
|
||||
__tracebackhide__ = True
|
||||
|
@ -548,7 +580,7 @@ def importorskip(modname, minversion=None):
|
|||
"""
|
||||
import warnings
|
||||
__tracebackhide__ = True
|
||||
compile(modname, '', 'eval') # to catch syntaxerrors
|
||||
compile(modname, '', 'eval') # to catch syntaxerrors
|
||||
should_skip = False
|
||||
|
||||
with warnings.catch_warnings():
|
||||
|
@ -562,7 +594,7 @@ def importorskip(modname, minversion=None):
|
|||
# Do not raise chained exception here(#1485)
|
||||
should_skip = True
|
||||
if should_skip:
|
||||
raise Skipped("could not import %r" %(modname,), allow_module_level=True)
|
||||
raise Skipped("could not import %r" % (modname,), allow_module_level=True)
|
||||
mod = sys.modules[modname]
|
||||
if minversion is None:
|
||||
return mod
|
||||
|
@ -575,6 +607,6 @@ def importorskip(modname, minversion=None):
|
|||
"pkg_resources to parse version strings." % (modname,),
|
||||
allow_module_level=True)
|
||||
if verattr is None or pv(verattr) < pv(minversion):
|
||||
raise Skipped("module %r has __version__ %r, required is: %r" %(
|
||||
raise Skipped("module %r has __version__ %r, required is: %r" % (
|
||||
modname, verattr, minversion), allow_module_level=True)
|
||||
return mod
|
||||
|
|
|
@ -10,11 +10,12 @@ from _pytest.config import hookimpl
|
|||
from _pytest.mark import MarkInfo, MarkDecorator
|
||||
from _pytest.runner import fail, skip
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
group.addoption('--runxfail',
|
||||
action="store_true", dest="runxfail", default=False,
|
||||
help="run tests even if they are marked xfail")
|
||||
action="store_true", dest="runxfail", default=False,
|
||||
help="run tests even if they are marked xfail")
|
||||
|
||||
parser.addini("xfail_strict", "default for the strict parameter of xfail "
|
||||
"markers when not given explicitly (default: "
|
||||
|
@ -37,26 +38,26 @@ def pytest_configure(config):
|
|||
setattr(pytest, "xfail", nop)
|
||||
|
||||
config.addinivalue_line("markers",
|
||||
"skip(reason=None): skip the given test function with an optional reason. "
|
||||
"Example: skip(reason=\"no way of currently testing this\") skips the "
|
||||
"test."
|
||||
)
|
||||
"skip(reason=None): skip the given test function with an optional reason. "
|
||||
"Example: skip(reason=\"no way of currently testing this\") skips the "
|
||||
"test."
|
||||
)
|
||||
config.addinivalue_line("markers",
|
||||
"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"
|
||||
)
|
||||
"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"
|
||||
)
|
||||
config.addinivalue_line("markers",
|
||||
"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"
|
||||
)
|
||||
"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"
|
||||
)
|
||||
|
||||
|
||||
class XFailed(fail.Exception):
|
||||
|
@ -243,7 +244,7 @@ def pytest_runtest_makereport(item, call):
|
|||
rep.wasxfail = "reason: " + call.excinfo.value.msg
|
||||
rep.outcome = "skipped"
|
||||
elif evalxfail and not rep.skipped and evalxfail.wasvalid() and \
|
||||
evalxfail.istrue():
|
||||
evalxfail.istrue():
|
||||
if call.excinfo:
|
||||
if evalxfail.invalidraise(call.excinfo.value):
|
||||
rep.outcome = "failed"
|
||||
|
@ -269,6 +270,8 @@ def pytest_runtest_makereport(item, call):
|
|||
rep.longrepr = filename, line, reason
|
||||
|
||||
# called by terminalreporter progress reporting
|
||||
|
||||
|
||||
def pytest_report_teststatus(report):
|
||||
if hasattr(report, "wasxfail"):
|
||||
if report.skipped:
|
||||
|
@ -277,10 +280,12 @@ def pytest_report_teststatus(report):
|
|||
return "xpassed", "X", ("XPASS", {'yellow': True})
|
||||
|
||||
# called by the terminalreporter instance/plugin
|
||||
|
||||
|
||||
def pytest_terminal_summary(terminalreporter):
|
||||
tr = terminalreporter
|
||||
if not tr.reportchars:
|
||||
#for name in "xfailed skipped failed xpassed":
|
||||
# for name in "xfailed skipped failed xpassed":
|
||||
# if not tr.stats.get(name, 0):
|
||||
# tr.write_line("HINT: use '-r' option to see extra "
|
||||
# "summary info about tests")
|
||||
|
@ -364,14 +369,14 @@ def show_skipped(terminalreporter, lines):
|
|||
tr = terminalreporter
|
||||
skipped = tr.stats.get('skipped', [])
|
||||
if skipped:
|
||||
#if not tr.hasopt('skipped'):
|
||||
# if not tr.hasopt('skipped'):
|
||||
# tr.write_line(
|
||||
# "%d skipped tests, specify -rs for more info" %
|
||||
# len(skipped))
|
||||
# return
|
||||
fskips = folded_skips(skipped)
|
||||
if fskips:
|
||||
#tr.write_sep("_", "skipped test summary")
|
||||
# tr.write_sep("_", "skipped test summary")
|
||||
for num, fspath, lineno, reason in fskips:
|
||||
if reason.startswith("Skipped: "):
|
||||
reason = reason[9:]
|
||||
|
|
|
@ -19,33 +19,34 @@ import _pytest._pluggy as pluggy
|
|||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("terminal reporting", "reporting", after="general")
|
||||
group._addoption('-v', '--verbose', action="count",
|
||||
dest="verbose", default=0, help="increase verbosity."),
|
||||
dest="verbose", default=0, help="increase verbosity."),
|
||||
group._addoption('-q', '--quiet', action="count",
|
||||
dest="quiet", default=0, help="decrease verbosity."),
|
||||
dest="quiet", default=0, help="decrease verbosity."),
|
||||
group._addoption('-r',
|
||||
action="store", dest="reportchars", default='', metavar="chars",
|
||||
help="show extra test summary info as specified by chars (f)ailed, "
|
||||
"(E)error, (s)skipped, (x)failed, (X)passed, "
|
||||
"(p)passed, (P)passed with output, (a)all except pP. "
|
||||
"Warnings are displayed at all times except when "
|
||||
"--disable-warnings is set")
|
||||
action="store", dest="reportchars", default='', metavar="chars",
|
||||
help="show extra test summary info as specified by chars (f)ailed, "
|
||||
"(E)error, (s)skipped, (x)failed, (X)passed, "
|
||||
"(p)passed, (P)passed with output, (a)all except pP. "
|
||||
"Warnings are displayed at all times except when "
|
||||
"--disable-warnings is set")
|
||||
group._addoption('--disable-warnings', '--disable-pytest-warnings', default=False,
|
||||
dest='disable_warnings', action='store_true',
|
||||
help='disable warnings summary')
|
||||
group._addoption('-l', '--showlocals',
|
||||
action="store_true", dest="showlocals", default=False,
|
||||
help="show locals in tracebacks (disabled by default).")
|
||||
action="store_true", dest="showlocals", default=False,
|
||||
help="show locals in tracebacks (disabled by default).")
|
||||
group._addoption('--tb', metavar="style",
|
||||
action="store", dest="tbstyle", default='auto',
|
||||
choices=['auto', 'long', 'short', 'no', 'line', 'native'],
|
||||
help="traceback print mode (auto/long/short/line/native/no).")
|
||||
action="store", dest="tbstyle", default='auto',
|
||||
choices=['auto', 'long', 'short', 'no', 'line', 'native'],
|
||||
help="traceback print mode (auto/long/short/line/native/no).")
|
||||
group._addoption('--fulltrace', '--full-trace',
|
||||
action="store_true", default=False,
|
||||
help="don't cut any tracebacks (default is to cut).")
|
||||
action="store_true", default=False,
|
||||
help="don't cut any tracebacks (default is to cut).")
|
||||
group._addoption('--color', metavar="color",
|
||||
action="store", dest="color", default='auto',
|
||||
choices=['yes', 'no', 'auto'],
|
||||
help="color terminal output (yes/no/auto).")
|
||||
action="store", dest="color", default='auto',
|
||||
choices=['yes', 'no', 'auto'],
|
||||
help="color terminal output (yes/no/auto).")
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
config.option.verbose -= config.option.quiet
|
||||
|
@ -57,6 +58,7 @@ def pytest_configure(config):
|
|||
reporter.write_line("[traceconfig] " + msg)
|
||||
config.trace.root.setprocessor("pytest:config", mywriter)
|
||||
|
||||
|
||||
def getreportopt(config):
|
||||
reportopts = ""
|
||||
reportchars = config.option.reportchars
|
||||
|
@ -72,6 +74,7 @@ def getreportopt(config):
|
|||
reportopts = 'fEsxXw'
|
||||
return reportopts
|
||||
|
||||
|
||||
def pytest_report_teststatus(report):
|
||||
if report.passed:
|
||||
letter = "."
|
||||
|
@ -88,6 +91,7 @@ class WarningReport:
|
|||
"""
|
||||
Simple structure to hold warnings information captured by ``pytest_logwarning``.
|
||||
"""
|
||||
|
||||
def __init__(self, code, message, nodeid=None, fslocation=None):
|
||||
"""
|
||||
:param code: unused
|
||||
|
@ -240,15 +244,15 @@ class TerminalReporter:
|
|||
word, markup = word
|
||||
else:
|
||||
if rep.passed:
|
||||
markup = {'green':True}
|
||||
markup = {'green': True}
|
||||
elif rep.failed:
|
||||
markup = {'red':True}
|
||||
markup = {'red': True}
|
||||
elif rep.skipped:
|
||||
markup = {'yellow':True}
|
||||
markup = {'yellow': True}
|
||||
line = self._locationline(rep.nodeid, *rep.location)
|
||||
if not hasattr(rep, 'node'):
|
||||
self.write_ensure_prefix(line, word, **markup)
|
||||
#self._tw.write(word, **markup)
|
||||
# self._tw.write(word, **markup)
|
||||
else:
|
||||
self.ensure_newline()
|
||||
if hasattr(rep, 'node'):
|
||||
|
@ -269,7 +273,7 @@ class TerminalReporter:
|
|||
items = [x for x in report.result if isinstance(x, pytest.Item)]
|
||||
self._numcollected += len(items)
|
||||
if self.isatty:
|
||||
#self.write_fspath_result(report.nodeid, 'E')
|
||||
# self.write_fspath_result(report.nodeid, 'E')
|
||||
self.report_collect()
|
||||
|
||||
def report_collect(self, final=False):
|
||||
|
@ -347,7 +351,7 @@ class TerminalReporter:
|
|||
return 0
|
||||
if not self.showheader:
|
||||
return
|
||||
#for i, testarg in enumerate(self.config.args):
|
||||
# for i, testarg in enumerate(self.config.args):
|
||||
# self.write_line("test path %d: %s" %(i+1, testarg))
|
||||
|
||||
def _printcollecteditems(self, items):
|
||||
|
@ -371,14 +375,14 @@ class TerminalReporter:
|
|||
stack = []
|
||||
indent = ""
|
||||
for item in items:
|
||||
needed_collectors = item.listchain()[1:] # strip root node
|
||||
needed_collectors = item.listchain()[1:] # strip root node
|
||||
while stack:
|
||||
if stack == needed_collectors[:len(stack)]:
|
||||
break
|
||||
stack.pop()
|
||||
for col in needed_collectors[len(stack):]:
|
||||
stack.append(col)
|
||||
#if col.name == "()":
|
||||
# if col.name == "()":
|
||||
# continue
|
||||
indent = (len(stack) - 1) * " "
|
||||
self._tw.line("%s%s" % (indent, col))
|
||||
|
@ -446,7 +450,7 @@ class TerminalReporter:
|
|||
fspath, lineno, domain = rep.location
|
||||
return domain
|
||||
else:
|
||||
return "test session" # XXX?
|
||||
return "test session" # XXX?
|
||||
|
||||
def _getcrashline(self, rep):
|
||||
try:
|
||||
|
@ -505,7 +509,6 @@ class TerminalReporter:
|
|||
content = content[:-1]
|
||||
self._tw.line(content)
|
||||
|
||||
|
||||
def summary_failures(self):
|
||||
if self.config.option.tbstyle != "no":
|
||||
reports = self.getreports('failed')
|
||||
|
@ -567,6 +570,7 @@ class TerminalReporter:
|
|||
self.write_sep("=", "%d tests deselected" % (
|
||||
len(self.stats['deselected'])), bold=True)
|
||||
|
||||
|
||||
def repr_pythonversion(v=None):
|
||||
if v is None:
|
||||
v = sys.version_info
|
||||
|
@ -575,6 +579,7 @@ def repr_pythonversion(v=None):
|
|||
except (TypeError, ValueError):
|
||||
return str(v)
|
||||
|
||||
|
||||
def flatten(l):
|
||||
for x in l:
|
||||
if isinstance(x, (list, tuple)):
|
||||
|
@ -583,13 +588,14 @@ def flatten(l):
|
|||
else:
|
||||
yield x
|
||||
|
||||
|
||||
def build_summary_stats_line(stats):
|
||||
keys = ("failed passed skipped deselected "
|
||||
"xfailed xpassed warnings error").split()
|
||||
unknown_key_seen = False
|
||||
for key in stats.keys():
|
||||
if key not in keys:
|
||||
if key: # setup/teardown reports have an empty key, ignore them
|
||||
if key: # setup/teardown reports have an empty key, ignore them
|
||||
keys.append(key)
|
||||
unknown_key_seen = True
|
||||
parts = []
|
||||
|
|
|
@ -25,7 +25,7 @@ class TempdirFactory:
|
|||
provides an empty unique-per-test-invocation directory
|
||||
and is guaranteed to be empty.
|
||||
"""
|
||||
#py.log._apiwarn(">1.1", "use tmpdir function argument")
|
||||
# py.log._apiwarn(">1.1", "use tmpdir function argument")
|
||||
return self.getbasetemp().ensure(string, dir=dir)
|
||||
|
||||
def mktemp(self, basename, numbered=True):
|
||||
|
@ -38,7 +38,7 @@ class TempdirFactory:
|
|||
p = basetemp.mkdir(basename)
|
||||
else:
|
||||
p = py.path.local.make_numbered_dir(prefix=basename,
|
||||
keep=0, rootdir=basetemp, lock_timeout=None)
|
||||
keep=0, rootdir=basetemp, lock_timeout=None)
|
||||
self.trace("mktemp", p)
|
||||
return p
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ class TestCaseFunction(Function):
|
|||
# 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)):
|
||||
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__', ''))
|
||||
|
@ -210,7 +210,7 @@ def pytest_runtest_protocol(item):
|
|||
check_testcase_implements_trial_reporter()
|
||||
|
||||
def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
|
||||
captureVars=None):
|
||||
captureVars=None):
|
||||
if exc_value is None:
|
||||
self._rawexcinfo = sys.exc_info()
|
||||
else:
|
||||
|
@ -219,7 +219,7 @@ def pytest_runtest_protocol(item):
|
|||
self._rawexcinfo = (exc_type, exc_value, exc_tb)
|
||||
try:
|
||||
Failure__init__(self, exc_value, exc_type, exc_tb,
|
||||
captureVars=captureVars)
|
||||
captureVars=captureVars)
|
||||
except TypeError:
|
||||
Failure__init__(self, exc_value, exc_type, exc_tb)
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ def catch_warnings_for_item(item):
|
|||
if unicode_warning:
|
||||
warnings.warn(
|
||||
"Warning is using unicode non convertible to ascii, "
|
||||
"converting to a safe representation:\n %s" % msg,
|
||||
"converting to a safe representation:\n %s" % msg,
|
||||
UnicodeWarning)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fixed all flake8 errors and warnings
|
|
@ -74,14 +74,13 @@ class TestGeneralUsage(object):
|
|||
print("---unconfigure")
|
||||
""")
|
||||
result = testdir.runpytest("-s", "asd")
|
||||
assert result.ret == 4 # EXIT_USAGEERROR
|
||||
assert result.ret == 4 # EXIT_USAGEERROR
|
||||
result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
|
||||
result.stdout.fnmatch_lines([
|
||||
"*---configure",
|
||||
"*---unconfigure",
|
||||
])
|
||||
|
||||
|
||||
def test_config_preparse_plugin_option(self, testdir):
|
||||
testdir.makepyfile(pytest_xyz="""
|
||||
def pytest_addoption(parser):
|
||||
|
@ -119,7 +118,7 @@ class TestGeneralUsage(object):
|
|||
testdir.makepyfile(import_fails="import does_not_work")
|
||||
result = testdir.runpytest(p)
|
||||
result.stdout.fnmatch_lines([
|
||||
#XXX on jython this fails: "> import import_fails",
|
||||
# XXX on jython this fails: "> import import_fails",
|
||||
"ImportError while importing test module*",
|
||||
"*No module named *does_not_work*",
|
||||
])
|
||||
|
@ -131,7 +130,7 @@ class TestGeneralUsage(object):
|
|||
result = testdir.runpytest(p1, p2)
|
||||
assert result.ret
|
||||
result.stderr.fnmatch_lines([
|
||||
"*ERROR: not found:*%s" %(p2.basename,)
|
||||
"*ERROR: not found:*%s" % (p2.basename,)
|
||||
])
|
||||
|
||||
def test_issue486_better_reporting_on_conftest_load_failure(self, testdir):
|
||||
|
@ -147,7 +146,6 @@ class TestGeneralUsage(object):
|
|||
*ERROR*could not load*conftest.py*
|
||||
""")
|
||||
|
||||
|
||||
def test_early_skip(self, testdir):
|
||||
testdir.mkdir("xyz")
|
||||
testdir.makeconftest("""
|
||||
|
@ -255,7 +253,7 @@ class TestGeneralUsage(object):
|
|||
if path.basename.startswith("conftest"):
|
||||
return MyCollector(path, parent)
|
||||
""")
|
||||
result = testdir.runpytest(c.basename+"::"+"xyz")
|
||||
result = testdir.runpytest(c.basename + "::" + "xyz")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*1 pass*",
|
||||
|
@ -310,7 +308,7 @@ class TestGeneralUsage(object):
|
|||
x
|
||||
""")
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 3 # internal error
|
||||
assert result.ret == 3 # internal error
|
||||
result.stderr.fnmatch_lines([
|
||||
"INTERNAL*pytest_configure*",
|
||||
"INTERNAL*x*",
|
||||
|
@ -410,7 +408,7 @@ class TestGeneralUsage(object):
|
|||
def test_stuff(r):
|
||||
pass
|
||||
"""
|
||||
)
|
||||
)
|
||||
res = testdir.runpytest(p)
|
||||
res.stdout.fnmatch_lines([
|
||||
'*1 passed*'
|
||||
|
@ -440,8 +438,8 @@ class TestInvocationVariants(object):
|
|||
#collect
|
||||
#cmdline
|
||||
#Item
|
||||
#assert collect.Item is Item
|
||||
#assert collect.Collector is Collector
|
||||
# assert collect.Item is Item
|
||||
# assert collect.Collector is Collector
|
||||
main
|
||||
skip
|
||||
xfail
|
||||
|
@ -676,7 +674,6 @@ class TestInvocationVariants(object):
|
|||
import _pytest.config
|
||||
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)."""
|
||||
assert request.config.pluginmanager.hasplugin('python')
|
||||
|
@ -719,12 +716,12 @@ class TestDurations(object):
|
|||
result = testdir.runpytest("--durations=0")
|
||||
assert result.ret == 0
|
||||
for x in "123":
|
||||
for y in 'call',: #'setup', 'call', 'teardown':
|
||||
for y in 'call', : # 'setup', 'call', 'teardown':
|
||||
for line in result.stdout.lines:
|
||||
if ("test_%s" % x) in line and y in line:
|
||||
break
|
||||
else:
|
||||
raise AssertionError("not found %s %s" % (x,y))
|
||||
raise AssertionError("not found %s %s" % (x, y))
|
||||
|
||||
def test_with_deselected(self, testdir):
|
||||
testdir.makepyfile(self.source)
|
||||
|
@ -764,6 +761,7 @@ class TestDurationWithFixture(object):
|
|||
def test_2():
|
||||
time.sleep(frag)
|
||||
"""
|
||||
|
||||
def test_setup_function(self, testdir):
|
||||
testdir.makepyfile(self.source)
|
||||
result = testdir.runpytest("--durations=10")
|
||||
|
|
|
@ -12,6 +12,7 @@ def test_ne():
|
|||
code2 = _pytest._code.Code(compile('foo = "baz"', '', 'exec'))
|
||||
assert code2 != code1
|
||||
|
||||
|
||||
def test_code_gives_back_name_for_not_existing_file():
|
||||
name = 'abc-123'
|
||||
co_code = compile("pass\n", name, 'exec')
|
||||
|
@ -20,6 +21,7 @@ def test_code_gives_back_name_for_not_existing_file():
|
|||
assert str(code.path) == name
|
||||
assert code.fullsource is None
|
||||
|
||||
|
||||
def test_code_with_class():
|
||||
class A(object):
|
||||
pass
|
||||
|
@ -30,11 +32,13 @@ if True:
|
|||
def x():
|
||||
pass
|
||||
|
||||
|
||||
def test_code_fullsource():
|
||||
code = _pytest._code.Code(x)
|
||||
full = code.fullsource
|
||||
assert 'test_code_fullsource()' in str(full)
|
||||
|
||||
|
||||
def test_code_source():
|
||||
code = _pytest._code.Code(x)
|
||||
src = code.source()
|
||||
|
@ -42,6 +46,7 @@ def test_code_source():
|
|||
pass"""
|
||||
assert str(src) == expected
|
||||
|
||||
|
||||
def test_frame_getsourcelineno_myself():
|
||||
def func():
|
||||
return sys._getframe(0)
|
||||
|
@ -50,6 +55,7 @@ def test_frame_getsourcelineno_myself():
|
|||
source, lineno = f.code.fullsource, f.lineno
|
||||
assert source[lineno].startswith(" return sys._getframe(0)")
|
||||
|
||||
|
||||
def test_getstatement_empty_fullsource():
|
||||
def func():
|
||||
return sys._getframe(0)
|
||||
|
@ -62,6 +68,7 @@ def test_getstatement_empty_fullsource():
|
|||
finally:
|
||||
f.code.__class__.fullsource = prop
|
||||
|
||||
|
||||
def test_code_from_func():
|
||||
co = _pytest._code.Code(test_frame_getsourcelineno_myself)
|
||||
assert co.firstlineno
|
||||
|
@ -92,6 +99,7 @@ def test_unicode_handling_syntax_error():
|
|||
if sys.version_info[0] < 3:
|
||||
unicode(excinfo)
|
||||
|
||||
|
||||
def test_code_getargs():
|
||||
def f1(x):
|
||||
pass
|
||||
|
@ -141,8 +149,10 @@ class TestExceptionInfo(object):
|
|||
|
||||
def test_bad_getsource(self):
|
||||
try:
|
||||
if False: pass
|
||||
else: assert False
|
||||
if False:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
except AssertionError:
|
||||
exci = _pytest._code.ExceptionInfo()
|
||||
assert exci.getrepr()
|
||||
|
@ -152,11 +162,13 @@ class TestTracebackEntry(object):
|
|||
|
||||
def test_getsource(self):
|
||||
try:
|
||||
if False: pass
|
||||
else: assert False
|
||||
if False:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
except AssertionError:
|
||||
exci = _pytest._code.ExceptionInfo()
|
||||
entry = exci.traceback[0]
|
||||
source = entry.getsource()
|
||||
assert len(source) == 4
|
||||
assert 'else: assert False' in source[3]
|
||||
assert len(source) == 6
|
||||
assert 'assert False' in source[5]
|
||||
|
|
|
@ -12,9 +12,6 @@ from _pytest._code.code import (
|
|||
ReprExceptionInfo,
|
||||
ExceptionChainRepr)
|
||||
|
||||
queue = py.builtin._tryimport('queue', 'Queue')
|
||||
|
||||
failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
|
||||
from test_source import astonly
|
||||
|
||||
try:
|
||||
|
@ -24,23 +21,32 @@ except ImportError:
|
|||
else:
|
||||
invalidate_import_caches = getattr(importlib, "invalidate_caches", None)
|
||||
|
||||
import pytest
|
||||
queue = py.builtin._tryimport('queue', 'Queue')
|
||||
|
||||
failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
|
||||
|
||||
pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3]))
|
||||
|
||||
|
||||
class TWMock(object):
|
||||
WRITE = object()
|
||||
|
||||
def __init__(self):
|
||||
self.lines = []
|
||||
self.is_writing = False
|
||||
|
||||
def sep(self, sep, line=None):
|
||||
self.lines.append((sep, line))
|
||||
|
||||
def write(self, msg, **kw):
|
||||
self.lines.append((TWMock.WRITE, msg))
|
||||
|
||||
def line(self, line, **kw):
|
||||
self.lines.append(line)
|
||||
|
||||
def markup(self, text, **kw):
|
||||
return text
|
||||
|
||||
def get_write_msg(self, idx):
|
||||
flag, msg = self.lines[idx]
|
||||
assert flag == TWMock.WRITE
|
||||
|
@ -48,6 +54,7 @@ class TWMock(object):
|
|||
|
||||
fullwidth = 80
|
||||
|
||||
|
||||
def test_excinfo_simple():
|
||||
try:
|
||||
raise ValueError
|
||||
|
@ -55,6 +62,7 @@ def test_excinfo_simple():
|
|||
info = _pytest._code.ExceptionInfo()
|
||||
assert info.type == ValueError
|
||||
|
||||
|
||||
def test_excinfo_getstatement():
|
||||
def g():
|
||||
raise ValueError
|
||||
|
@ -72,25 +80,32 @@ def test_excinfo_getstatement():
|
|||
l = list(excinfo.traceback)
|
||||
foundlinenumbers = [x.lineno for x in l]
|
||||
assert foundlinenumbers == linenumbers
|
||||
#for x in info:
|
||||
# for x in info:
|
||||
# print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
|
||||
#xxx
|
||||
# xxx
|
||||
|
||||
# testchain for getentries test below
|
||||
|
||||
|
||||
def f():
|
||||
#
|
||||
raise ValueError
|
||||
#
|
||||
|
||||
|
||||
def g():
|
||||
#
|
||||
__tracebackhide__ = True
|
||||
f()
|
||||
#
|
||||
|
||||
|
||||
def h():
|
||||
#
|
||||
g()
|
||||
#
|
||||
|
||||
|
||||
class TestTraceback_f_g_h(object):
|
||||
def setup_method(self, method):
|
||||
try:
|
||||
|
@ -101,8 +116,8 @@ class TestTraceback_f_g_h(object):
|
|||
def test_traceback_entries(self):
|
||||
tb = self.excinfo.traceback
|
||||
entries = list(tb)
|
||||
assert len(tb) == 4 # maybe fragile test
|
||||
assert len(entries) == 4 # maybe fragile test
|
||||
assert len(tb) == 4 # maybe fragile test
|
||||
assert len(entries) == 4 # maybe fragile test
|
||||
names = ['f', 'g', 'h']
|
||||
for entry in entries:
|
||||
try:
|
||||
|
@ -113,7 +128,7 @@ class TestTraceback_f_g_h(object):
|
|||
|
||||
def test_traceback_entry_getsource(self):
|
||||
tb = self.excinfo.traceback
|
||||
s = str(tb[-1].getsource() )
|
||||
s = str(tb[-1].getsource())
|
||||
assert s.startswith("def f():")
|
||||
assert s.endswith("raise ValueError")
|
||||
|
||||
|
@ -143,7 +158,7 @@ class TestTraceback_f_g_h(object):
|
|||
traceback = self.excinfo.traceback
|
||||
newtraceback = traceback.cut(path=path, firstlineno=firstlineno)
|
||||
assert len(newtraceback) == 1
|
||||
newtraceback = traceback.cut(path=path, lineno=firstlineno+2)
|
||||
newtraceback = traceback.cut(path=path, lineno=firstlineno + 2)
|
||||
assert len(newtraceback) == 1
|
||||
|
||||
def test_traceback_cut_excludepath(self, testdir):
|
||||
|
@ -210,7 +225,7 @@ class TestTraceback_f_g_h(object):
|
|||
def f(n):
|
||||
if n == 0:
|
||||
raise RuntimeError("hello")
|
||||
f(n-1)
|
||||
f(n - 1)
|
||||
|
||||
excinfo = pytest.raises(RuntimeError, f, 100)
|
||||
monkeypatch.delattr(excinfo.traceback.__class__, "recursionindex")
|
||||
|
@ -238,7 +253,7 @@ class TestTraceback_f_g_h(object):
|
|||
assert recindex is None
|
||||
|
||||
def test_traceback_messy_recursion(self):
|
||||
#XXX: simplified locally testable version
|
||||
# XXX: simplified locally testable version
|
||||
decorator = pytest.importorskip('decorator').decorator
|
||||
|
||||
def log(f, *k, **kw):
|
||||
|
@ -294,44 +309,50 @@ class TestTraceback_f_g_h(object):
|
|||
assert entry.lineno == co.firstlineno + 2
|
||||
assert entry.frame.code.name == 'g'
|
||||
|
||||
|
||||
def test_excinfo_exconly():
|
||||
excinfo = pytest.raises(ValueError, h)
|
||||
assert excinfo.exconly().startswith('ValueError')
|
||||
excinfo = pytest.raises(ValueError,
|
||||
"raise ValueError('hello\\nworld')")
|
||||
"raise ValueError('hello\\nworld')")
|
||||
msg = excinfo.exconly(tryshort=True)
|
||||
assert msg.startswith('ValueError')
|
||||
assert msg.endswith("world")
|
||||
|
||||
|
||||
def test_excinfo_repr():
|
||||
excinfo = pytest.raises(ValueError, h)
|
||||
s = repr(excinfo)
|
||||
assert s == "<ExceptionInfo ValueError tblen=4>"
|
||||
|
||||
|
||||
def test_excinfo_str():
|
||||
excinfo = pytest.raises(ValueError, h)
|
||||
s = str(excinfo)
|
||||
assert s.startswith(__file__[:-9]) # pyc file and $py.class
|
||||
assert s.startswith(__file__[:-9]) # pyc file and $py.class
|
||||
assert s.endswith("ValueError")
|
||||
assert len(s.split(":")) >= 3 # on windows it's 4
|
||||
assert len(s.split(":")) >= 3 # on windows it's 4
|
||||
|
||||
|
||||
def test_excinfo_errisinstance():
|
||||
excinfo = pytest.raises(ValueError, h)
|
||||
assert excinfo.errisinstance(ValueError)
|
||||
|
||||
|
||||
def test_excinfo_no_sourcecode():
|
||||
try:
|
||||
exec ("raise ValueError()")
|
||||
except ValueError:
|
||||
excinfo = _pytest._code.ExceptionInfo()
|
||||
s = str(excinfo.traceback[-1])
|
||||
if py.std.sys.version_info < (2,5):
|
||||
if py.std.sys.version_info < (2, 5):
|
||||
assert s == " File '<string>':1 in ?\n ???\n"
|
||||
else:
|
||||
assert s == " File '<string>':1 in <module>\n ???\n"
|
||||
|
||||
|
||||
def test_excinfo_no_python_sourcecode(tmpdir):
|
||||
#XXX: simplified locally testable version
|
||||
# XXX: simplified locally testable version
|
||||
tmpdir.join('test.txt').write("{{ h()}}:")
|
||||
|
||||
jinja2 = pytest.importorskip('jinja2')
|
||||
|
@ -339,10 +360,10 @@ def test_excinfo_no_python_sourcecode(tmpdir):
|
|||
env = jinja2.Environment(loader=loader)
|
||||
template = env.get_template('test.txt')
|
||||
excinfo = pytest.raises(ValueError,
|
||||
template.render, h=h)
|
||||
template.render, h=h)
|
||||
for item in excinfo.traceback:
|
||||
print(item) #XXX: for some reason jinja.Template.render is printed in full
|
||||
item.source # shouldnt fail
|
||||
print(item) # XXX: for some reason jinja.Template.render is printed in full
|
||||
item.source # shouldnt fail
|
||||
if item.path.basename == 'test.txt':
|
||||
assert str(item.source) == '{{ h()}}:'
|
||||
|
||||
|
@ -358,6 +379,7 @@ def test_entrysource_Queue_example():
|
|||
s = str(source).strip()
|
||||
assert s.startswith("def get")
|
||||
|
||||
|
||||
def test_codepath_Queue_example():
|
||||
try:
|
||||
queue.Queue().get(timeout=0.001)
|
||||
|
@ -369,11 +391,13 @@ def test_codepath_Queue_example():
|
|||
assert path.basename.lower() == "queue.py"
|
||||
assert path.check()
|
||||
|
||||
|
||||
def test_match_succeeds():
|
||||
with pytest.raises(ZeroDivisionError) as excinfo:
|
||||
0 // 0
|
||||
excinfo.match(r'.*zero.*')
|
||||
|
||||
|
||||
def test_match_raises_error(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -388,6 +412,7 @@ def test_match_raises_error(testdir):
|
|||
"*AssertionError*Pattern*[123]*not found*",
|
||||
])
|
||||
|
||||
|
||||
class TestFormattedExcinfo(object):
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -442,7 +467,6 @@ class TestFormattedExcinfo(object):
|
|||
'E AssertionError'
|
||||
]
|
||||
|
||||
|
||||
def test_repr_source_not_existing(self):
|
||||
pr = FormattedExcinfo()
|
||||
co = compile("raise ValueError()", "", "exec")
|
||||
|
@ -492,7 +516,7 @@ raise ValueError()
|
|||
|
||||
class FakeTracebackEntry(_pytest._code.Traceback.Entry):
|
||||
def __init__(self, tb, excinfo=None):
|
||||
self.lineno = 5+3
|
||||
self.lineno = 5 + 3
|
||||
|
||||
@property
|
||||
def frame(self):
|
||||
|
@ -528,14 +552,12 @@ raise ValueError()
|
|||
if py.std.sys.version_info[0] >= 3:
|
||||
assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
|
||||
|
||||
|
||||
fail = py.error.ENOENT # noqa
|
||||
repr = pr.repr_excinfo(excinfo)
|
||||
assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
|
||||
if py.std.sys.version_info[0] >= 3:
|
||||
assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
|
||||
|
||||
|
||||
def test_repr_local(self):
|
||||
p = FormattedExcinfo(showlocals=True)
|
||||
loc = {'y': 5, 'z': 7, 'x': 3, '@x': 2, '__builtins__': {}}
|
||||
|
@ -575,19 +597,19 @@ raise ValueError()
|
|||
loc = repr_entry.reprfileloc
|
||||
assert loc.path == mod.__file__
|
||||
assert loc.lineno == 3
|
||||
#assert loc.message == "ValueError: hello"
|
||||
# assert loc.message == "ValueError: hello"
|
||||
|
||||
def test_repr_tracebackentry_lines2(self, importasmod):
|
||||
mod = importasmod("""
|
||||
def func1(m, x, y, z):
|
||||
raise ValueError("hello\\nworld")
|
||||
""")
|
||||
excinfo = pytest.raises(ValueError, mod.func1, "m"*90, 5, 13, "z"*120)
|
||||
excinfo = pytest.raises(ValueError, mod.func1, "m" * 90, 5, 13, "z" * 120)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
entry = excinfo.traceback[-1]
|
||||
p = FormattedExcinfo(funcargs=True)
|
||||
reprfuncargs = p.repr_args(entry)
|
||||
assert reprfuncargs.args[0] == ('m', repr("m"*90))
|
||||
assert reprfuncargs.args[0] == ('m', repr("m" * 90))
|
||||
assert reprfuncargs.args[1] == ('x', '5')
|
||||
assert reprfuncargs.args[2] == ('y', '13')
|
||||
assert reprfuncargs.args[3] == ('z', repr("z" * 120))
|
||||
|
@ -934,10 +956,10 @@ raise ValueError()
|
|||
@pytest.mark.parametrize('reproptions', [
|
||||
{'style': style, 'showlocals': showlocals,
|
||||
'funcargs': funcargs, 'tbfilter': tbfilter
|
||||
} for style in ("long", "short", "no")
|
||||
for showlocals in (True, False)
|
||||
for tbfilter in (True, False)
|
||||
for funcargs in (True, False)])
|
||||
} for style in ("long", "short", "no")
|
||||
for showlocals in (True, False)
|
||||
for tbfilter in (True, False)
|
||||
for funcargs in (True, False)])
|
||||
def test_format_excinfo(self, importasmod, reproptions):
|
||||
mod = importasmod("""
|
||||
def g(x):
|
||||
|
@ -969,7 +991,8 @@ raise ValueError()
|
|||
r = excinfo.getrepr(style="long")
|
||||
tw = TWMock()
|
||||
r.toterminal(tw)
|
||||
for line in tw.lines: print (line)
|
||||
for line in tw.lines:
|
||||
print (line)
|
||||
assert tw.lines[0] == ""
|
||||
assert tw.lines[1] == " def f():"
|
||||
assert tw.lines[2] == "> g()"
|
||||
|
@ -1016,19 +1039,20 @@ raise ValueError()
|
|||
r = excinfo.getrepr(style="long")
|
||||
tw = TWMock()
|
||||
r.toterminal(tw)
|
||||
for line in tw.lines: print (line)
|
||||
assert tw.lines[0] == ""
|
||||
assert tw.lines[1] == " def f():"
|
||||
assert tw.lines[2] == " try:"
|
||||
assert tw.lines[3] == "> g()"
|
||||
assert tw.lines[4] == ""
|
||||
for line in tw.lines:
|
||||
print (line)
|
||||
assert tw.lines[0] == ""
|
||||
assert tw.lines[1] == " def f():"
|
||||
assert tw.lines[2] == " try:"
|
||||
assert tw.lines[3] == "> g()"
|
||||
assert tw.lines[4] == ""
|
||||
line = tw.get_write_msg(5)
|
||||
assert line.endswith('mod.py')
|
||||
assert tw.lines[6] == ':6: '
|
||||
assert tw.lines[7] == ("_ ", None)
|
||||
assert tw.lines[8] == ""
|
||||
assert tw.lines[9] == " def g():"
|
||||
assert tw.lines[10] == "> raise ValueError()"
|
||||
assert tw.lines[6] == ':6: '
|
||||
assert tw.lines[7] == ("_ ", None)
|
||||
assert tw.lines[8] == ""
|
||||
assert tw.lines[9] == " def g():"
|
||||
assert tw.lines[10] == "> raise ValueError()"
|
||||
assert tw.lines[11] == "E ValueError"
|
||||
assert tw.lines[12] == ""
|
||||
line = tw.get_write_msg(13)
|
||||
|
|
|
@ -17,6 +17,7 @@ else:
|
|||
|
||||
failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
|
||||
|
||||
|
||||
def test_source_str_function():
|
||||
x = Source("3")
|
||||
assert str(x) == "3"
|
||||
|
@ -34,6 +35,7 @@ def test_source_str_function():
|
|||
""", rstrip=True)
|
||||
assert str(x) == "\n3"
|
||||
|
||||
|
||||
def test_unicode():
|
||||
try:
|
||||
unicode
|
||||
|
@ -45,10 +47,12 @@ def test_unicode():
|
|||
val = eval(co)
|
||||
assert isinstance(val, unicode)
|
||||
|
||||
|
||||
def test_source_from_function():
|
||||
source = _pytest._code.Source(test_source_str_function)
|
||||
assert str(source).startswith('def test_source_str_function():')
|
||||
|
||||
|
||||
def test_source_from_method():
|
||||
class TestClass(object):
|
||||
def test_method(self):
|
||||
|
@ -57,11 +61,13 @@ def test_source_from_method():
|
|||
assert source.lines == ["def test_method(self):",
|
||||
" pass"]
|
||||
|
||||
|
||||
def test_source_from_lines():
|
||||
lines = ["a \n", "b\n", "c"]
|
||||
source = _pytest._code.Source(lines)
|
||||
assert source.lines == ['a ', 'b', 'c']
|
||||
|
||||
|
||||
def test_source_from_inner_function():
|
||||
def f():
|
||||
pass
|
||||
|
@ -70,6 +76,7 @@ def test_source_from_inner_function():
|
|||
source = _pytest._code.Source(f)
|
||||
assert str(source).startswith('def f():')
|
||||
|
||||
|
||||
def test_source_putaround_simple():
|
||||
source = Source("raise ValueError")
|
||||
source = source.putaround(
|
||||
|
@ -78,7 +85,7 @@ def test_source_putaround_simple():
|
|||
x = 42
|
||||
else:
|
||||
x = 23""")
|
||||
assert str(source)=="""\
|
||||
assert str(source) == """\
|
||||
try:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
|
@ -86,6 +93,7 @@ except ValueError:
|
|||
else:
|
||||
x = 23"""
|
||||
|
||||
|
||||
def test_source_putaround():
|
||||
source = Source()
|
||||
source = source.putaround("""
|
||||
|
@ -94,24 +102,28 @@ def test_source_putaround():
|
|||
""")
|
||||
assert str(source).strip() == "if 1:\n x=1"
|
||||
|
||||
|
||||
def test_source_strips():
|
||||
source = Source("")
|
||||
assert source == Source()
|
||||
assert str(source) == ''
|
||||
assert source.strip() == source
|
||||
|
||||
|
||||
def test_source_strip_multiline():
|
||||
source = Source()
|
||||
source.lines = ["", " hello", " "]
|
||||
source2 = source.strip()
|
||||
assert source2.lines == [" hello"]
|
||||
|
||||
|
||||
def test_syntaxerror_rerepresentation():
|
||||
ex = pytest.raises(SyntaxError, _pytest._code.compile, 'xyz xyz')
|
||||
assert ex.value.lineno == 1
|
||||
assert ex.value.offset in (4,7) # XXX pypy/jython versus cpython?
|
||||
assert ex.value.offset in (4, 7) # XXX pypy/jython versus cpython?
|
||||
assert ex.value.text.strip(), 'x x'
|
||||
|
||||
|
||||
def test_isparseable():
|
||||
assert Source("hello").isparseable()
|
||||
assert Source("if 1:\n pass").isparseable()
|
||||
|
@ -120,6 +132,7 @@ def test_isparseable():
|
|||
assert not Source(" \nif 1:\npass").isparseable()
|
||||
assert not Source(chr(0)).isparseable()
|
||||
|
||||
|
||||
class TestAccesses(object):
|
||||
source = Source("""\
|
||||
def f(x):
|
||||
|
@ -127,6 +140,7 @@ class TestAccesses(object):
|
|||
def g(x):
|
||||
pass
|
||||
""")
|
||||
|
||||
def test_getrange(self):
|
||||
x = self.source[0:2]
|
||||
assert x.isparseable()
|
||||
|
@ -144,6 +158,7 @@ class TestAccesses(object):
|
|||
l = [x for x in self.source]
|
||||
assert len(l) == 4
|
||||
|
||||
|
||||
class TestSourceParsingAndCompiling(object):
|
||||
source = Source("""\
|
||||
def f(x):
|
||||
|
@ -181,16 +196,16 @@ class TestSourceParsingAndCompiling(object):
|
|||
assert 'ValueError' in source2
|
||||
|
||||
def test_getstatement(self):
|
||||
#print str(self.source)
|
||||
# print str(self.source)
|
||||
ass = str(self.source[1:])
|
||||
for i in range(1, 4):
|
||||
#print "trying start in line %r" % self.source[i]
|
||||
# print "trying start in line %r" % self.source[i]
|
||||
s = self.source.getstatement(i)
|
||||
#x = s.deindent()
|
||||
assert str(s) == ass
|
||||
|
||||
def test_getstatementrange_triple_quoted(self):
|
||||
#print str(self.source)
|
||||
# print str(self.source)
|
||||
source = Source("""hello('''
|
||||
''')""")
|
||||
s = source.getstatement(0)
|
||||
|
@ -211,12 +226,12 @@ class TestSourceParsingAndCompiling(object):
|
|||
""")
|
||||
assert len(source) == 7
|
||||
# check all lineno's that could occur in a traceback
|
||||
#assert source.getstatementrange(0) == (0, 7)
|
||||
#assert source.getstatementrange(1) == (1, 5)
|
||||
# assert source.getstatementrange(0) == (0, 7)
|
||||
# assert source.getstatementrange(1) == (1, 5)
|
||||
assert source.getstatementrange(2) == (2, 3)
|
||||
assert source.getstatementrange(3) == (3, 4)
|
||||
assert source.getstatementrange(4) == (4, 5)
|
||||
#assert source.getstatementrange(5) == (0, 7)
|
||||
# assert source.getstatementrange(5) == (0, 7)
|
||||
assert source.getstatementrange(6) == (6, 7)
|
||||
|
||||
def test_getstatementrange_bug(self):
|
||||
|
@ -262,7 +277,7 @@ class TestSourceParsingAndCompiling(object):
|
|||
def test_getstatementrange_out_of_bounds_py3(self):
|
||||
source = Source("if xxx:\n from .collections import something")
|
||||
r = source.getstatementrange(1)
|
||||
assert r == (1,2)
|
||||
assert r == (1, 2)
|
||||
|
||||
def test_getstatementrange_with_syntaxerror_issue7(self):
|
||||
source = Source(":")
|
||||
|
@ -283,7 +298,7 @@ class TestSourceParsingAndCompiling(object):
|
|||
excinfo = pytest.raises(AssertionError, "f(6)")
|
||||
frame = excinfo.traceback[-1].frame
|
||||
stmt = frame.code.fullsource.getstatement(frame.lineno)
|
||||
#print "block", str(block)
|
||||
# print "block", str(block)
|
||||
assert str(stmt).strip().startswith('assert')
|
||||
|
||||
@pytest.mark.parametrize('name', ['', None, 'my'])
|
||||
|
@ -291,9 +306,9 @@ class TestSourceParsingAndCompiling(object):
|
|||
def check(comp, name):
|
||||
co = comp(self.source, name)
|
||||
if not name:
|
||||
expected = "codegen %s:%d>" %(mypath, mylineno+2+2)
|
||||
expected = "codegen %s:%d>" % (mypath, mylineno + 2 + 2)
|
||||
else:
|
||||
expected = "codegen %r %s:%d>" % (name, mypath, mylineno+2+2)
|
||||
expected = "codegen %r %s:%d>" % (name, mypath, mylineno + 2 + 2)
|
||||
fn = co.co_filename
|
||||
assert fn.endswith(expected)
|
||||
|
||||
|
@ -307,6 +322,7 @@ class TestSourceParsingAndCompiling(object):
|
|||
def test_offsetless_synerr(self):
|
||||
pytest.raises(SyntaxError, _pytest._code.compile, "lambda a,a: 0", mode='eval')
|
||||
|
||||
|
||||
def test_getstartingblock_singleline():
|
||||
class A(object):
|
||||
def __init__(self, *args):
|
||||
|
@ -318,6 +334,7 @@ def test_getstartingblock_singleline():
|
|||
l = [i for i in x.source.lines if i.strip()]
|
||||
assert len(l) == 1
|
||||
|
||||
|
||||
def test_getstartingblock_multiline():
|
||||
class A(object):
|
||||
def __init__(self, *args):
|
||||
|
@ -325,13 +342,14 @@ def test_getstartingblock_multiline():
|
|||
self.source = _pytest._code.Frame(frame).statement
|
||||
|
||||
x = A('x',
|
||||
'y' \
|
||||
'y'
|
||||
,
|
||||
'z')
|
||||
|
||||
l = [i for i in x.source.lines if i.strip()]
|
||||
assert len(l) == 4
|
||||
|
||||
|
||||
def test_getline_finally():
|
||||
def c(): pass
|
||||
excinfo = pytest.raises(TypeError, """
|
||||
|
@ -345,6 +363,7 @@ def test_getline_finally():
|
|||
source = excinfo.traceback[-1].statement
|
||||
assert str(source).strip() == 'c(1)'
|
||||
|
||||
|
||||
def test_getfuncsource_dynamic():
|
||||
source = """
|
||||
def f():
|
||||
|
@ -386,6 +405,7 @@ def test_deindent():
|
|||
lines = deindent(source.splitlines())
|
||||
assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
|
||||
|
||||
|
||||
@pytest.mark.xfail("sys.version_info[:3] < (2,7,0)")
|
||||
def test_source_of_class_at_eof_without_newline(tmpdir):
|
||||
# this test fails because the implicit inspect.getsource(A) below
|
||||
|
@ -400,10 +420,12 @@ def test_source_of_class_at_eof_without_newline(tmpdir):
|
|||
s2 = _pytest._code.Source(tmpdir.join("a.py").pyimport().A)
|
||||
assert str(source).strip() == str(s2).strip()
|
||||
|
||||
|
||||
if True:
|
||||
def x():
|
||||
pass
|
||||
|
||||
|
||||
def test_getsource_fallback():
|
||||
from _pytest._code.source import getsource
|
||||
expected = """def x():
|
||||
|
@ -411,6 +433,7 @@ def test_getsource_fallback():
|
|||
src = getsource(x)
|
||||
assert src == expected
|
||||
|
||||
|
||||
def test_idem_compile_and_getsource():
|
||||
from _pytest._code.source import getsource
|
||||
expected = "def x(): pass"
|
||||
|
@ -418,12 +441,14 @@ def test_idem_compile_and_getsource():
|
|||
src = getsource(co)
|
||||
assert src == expected
|
||||
|
||||
|
||||
def test_findsource_fallback():
|
||||
from _pytest._code.source import findsource
|
||||
src, lineno = findsource(x)
|
||||
assert 'test_findsource_simple' in str(src)
|
||||
assert src[lineno] == ' def x():'
|
||||
|
||||
|
||||
def test_findsource():
|
||||
from _pytest._code.source import findsource
|
||||
co = _pytest._code.compile("""if 1:
|
||||
|
@ -450,7 +475,7 @@ def test_getfslineno():
|
|||
fspath, lineno = getfslineno(f)
|
||||
|
||||
assert fspath.basename == "test_source.py"
|
||||
assert lineno == _pytest._code.getrawcode(f).co_firstlineno - 1 # see findsource
|
||||
assert lineno == _pytest._code.getrawcode(f).co_firstlineno - 1 # see findsource
|
||||
|
||||
class A(object):
|
||||
pass
|
||||
|
@ -462,15 +487,18 @@ def test_getfslineno():
|
|||
assert lineno == A_lineno
|
||||
|
||||
assert getfslineno(3) == ("", -1)
|
||||
|
||||
class B(object):
|
||||
pass
|
||||
B.__name__ = "B2"
|
||||
assert getfslineno(B)[1] == -1
|
||||
|
||||
|
||||
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
|
||||
|
@ -490,10 +518,12 @@ def getstatement(lineno, source):
|
|||
ast, start, end = getstatementrange_ast(lineno, source)
|
||||
return source[start:end]
|
||||
|
||||
|
||||
def test_oneline():
|
||||
source = getstatement(0, "raise ValueError")
|
||||
assert str(source) == "raise ValueError"
|
||||
|
||||
|
||||
def test_comment_and_no_newline_at_end():
|
||||
from _pytest._code.source import getstatementrange_ast
|
||||
source = Source(['def test_basic_complex():',
|
||||
|
@ -502,10 +532,12 @@ def test_comment_and_no_newline_at_end():
|
|||
ast, start, end = getstatementrange_ast(1, source)
|
||||
assert end == 2
|
||||
|
||||
|
||||
def test_oneline_and_comment():
|
||||
source = getstatement(0, "raise ValueError\n#hello")
|
||||
assert str(source) == "raise ValueError"
|
||||
|
||||
|
||||
@pytest.mark.xfail(hasattr(sys, "pypy_version_info"),
|
||||
reason='does not work on pypy')
|
||||
def test_comments():
|
||||
|
@ -521,29 +553,33 @@ def test_comments():
|
|||
comment 4
|
||||
"""
|
||||
'''
|
||||
for line in range(2,6):
|
||||
for line in range(2, 6):
|
||||
assert str(getstatement(line, source)) == ' x = 1'
|
||||
for line in range(6,10):
|
||||
for line in range(6, 10):
|
||||
assert str(getstatement(line, source)) == ' assert False'
|
||||
assert str(getstatement(10, source)) == '"""'
|
||||
|
||||
|
||||
def test_comment_in_statement():
|
||||
source = '''test(foo=1,
|
||||
# comment 1
|
||||
bar=2)
|
||||
'''
|
||||
for line in range(1,3):
|
||||
for line in range(1, 3):
|
||||
assert str(getstatement(line, source)) == \
|
||||
'test(foo=1,\n # comment 1\n bar=2)'
|
||||
'test(foo=1,\n # comment 1\n bar=2)'
|
||||
|
||||
|
||||
def test_single_line_else():
|
||||
source = getstatement(1, "if False: 2\nelse: 3")
|
||||
assert str(source) == "else: 3"
|
||||
|
||||
|
||||
def test_single_line_finally():
|
||||
source = getstatement(1, "try: 1\nfinally: 3")
|
||||
assert str(source) == "finally: 3"
|
||||
|
||||
|
||||
def test_issue55():
|
||||
source = ('def round_trip(dinp):\n assert 1 == dinp\n'
|
||||
'def test_rt():\n round_trip("""\n""")\n')
|
||||
|
@ -560,6 +596,7 @@ x = 3
|
|||
""")
|
||||
assert str(source) == "raise ValueError(\n 23\n)"
|
||||
|
||||
|
||||
class TestTry(object):
|
||||
pytestmark = astonly
|
||||
source = """\
|
||||
|
@ -587,6 +624,7 @@ else:
|
|||
source = getstatement(5, self.source)
|
||||
assert str(source) == " raise KeyError()"
|
||||
|
||||
|
||||
class TestTryFinally(object):
|
||||
source = """\
|
||||
try:
|
||||
|
@ -604,7 +642,6 @@ finally:
|
|||
assert str(source) == " raise IndexError(1)"
|
||||
|
||||
|
||||
|
||||
class TestIf(object):
|
||||
pytestmark = astonly
|
||||
source = """\
|
||||
|
@ -632,6 +669,7 @@ else:
|
|||
source = getstatement(5, self.source)
|
||||
assert str(source) == " y = 7"
|
||||
|
||||
|
||||
def test_semicolon():
|
||||
s = """\
|
||||
hello ; pytest.skip()
|
||||
|
@ -639,6 +677,7 @@ hello ; pytest.skip()
|
|||
source = getstatement(0, s)
|
||||
assert str(source) == s.strip()
|
||||
|
||||
|
||||
def test_def_online():
|
||||
s = """\
|
||||
def func(): raise ValueError(42)
|
||||
|
@ -649,6 +688,7 @@ def something():
|
|||
source = getstatement(0, s)
|
||||
assert str(source) == "def func(): raise ValueError(42)"
|
||||
|
||||
|
||||
def XXX_test_expression_multiline():
|
||||
source = """\
|
||||
something
|
||||
|
|
|
@ -10,4 +10,3 @@ if __name__ == '__main__':
|
|||
hidden.extend(['--hidden-import', x])
|
||||
args = ['pyinstaller', '--noconfirm'] + hidden + ['runtests_script.py']
|
||||
subprocess.check_call(' '.join(args), shell=True)
|
||||
|
||||
|
|
|
@ -6,4 +6,4 @@ py.test main().
|
|||
if __name__ == '__main__':
|
||||
import sys
|
||||
import pytest
|
||||
sys.exit(pytest.main())
|
||||
sys.exit(pytest.main())
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
def test_upper():
|
||||
assert 'foo'.upper() == 'FOO'
|
||||
|
||||
|
||||
def test_lower():
|
||||
assert 'FOO'.lower() == 'foo'
|
||||
assert 'FOO'.lower() == 'foo'
|
||||
|
|
|
@ -9,4 +9,4 @@ if __name__ == '__main__':
|
|||
executable = os.path.join(os.getcwd(), 'dist', 'runtests_script', 'runtests_script')
|
||||
if sys.platform.startswith('win'):
|
||||
executable += '.exe'
|
||||
sys.exit(os.system('%s tests' % executable))
|
||||
sys.exit(os.system('%s tests' % executable))
|
||||
|
|
|
@ -29,7 +29,8 @@ class TestApprox(object):
|
|||
if sys.version_info[:2] == (2, 6):
|
||||
tol1, tol2, infr = '???', '???', '???'
|
||||
assert repr(approx(1.0)) == '1.0 {pm} {tol1}'.format(pm=plus_minus, tol1=tol1)
|
||||
assert repr(approx([1.0, 2.0])) == '1.0 {pm} {tol1}, 2.0 {pm} {tol2}'.format(pm=plus_minus, tol1=tol1, tol2=tol2)
|
||||
assert repr(approx([1.0, 2.0])) == '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)
|
||||
|
@ -43,30 +44,30 @@ class TestApprox(object):
|
|||
|
||||
def test_exactly_equal(self):
|
||||
examples = [
|
||||
(2.0, 2.0),
|
||||
(0.1e200, 0.1e200),
|
||||
(1.123e-300, 1.123e-300),
|
||||
(12345, 12345.0),
|
||||
(0.0, -0.0),
|
||||
(345678, 345678),
|
||||
(Decimal('1.0001'), Decimal('1.0001')),
|
||||
(Fraction(1, 3), Fraction(-1, -3)),
|
||||
(2.0, 2.0),
|
||||
(0.1e200, 0.1e200),
|
||||
(1.123e-300, 1.123e-300),
|
||||
(12345, 12345.0),
|
||||
(0.0, -0.0),
|
||||
(345678, 345678),
|
||||
(Decimal('1.0001'), Decimal('1.0001')),
|
||||
(Fraction(1, 3), Fraction(-1, -3)),
|
||||
]
|
||||
for a, x in examples:
|
||||
assert a == approx(x)
|
||||
|
||||
def test_opposite_sign(self):
|
||||
examples = [
|
||||
(eq, 1e-100, -1e-100),
|
||||
(ne, 1e100, -1e100),
|
||||
(eq, 1e-100, -1e-100),
|
||||
(ne, 1e100, -1e100),
|
||||
]
|
||||
for op, a, x in examples:
|
||||
assert op(a, approx(x))
|
||||
|
||||
def test_zero_tolerance(self):
|
||||
within_1e10 = [
|
||||
(1.1e-100, 1e-100),
|
||||
(-1.1e-100, -1e-100),
|
||||
(1.1e-100, 1e-100),
|
||||
(-1.1e-100, -1e-100),
|
||||
]
|
||||
for a, x in within_1e10:
|
||||
assert x == approx(x, rel=0.0, abs=0.0)
|
||||
|
@ -79,11 +80,11 @@ class TestApprox(object):
|
|||
def test_negative_tolerance(self):
|
||||
# Negative tolerances are not allowed.
|
||||
illegal_kwargs = [
|
||||
dict(rel=-1e100),
|
||||
dict(abs=-1e100),
|
||||
dict(rel=1e100, abs=-1e100),
|
||||
dict(rel=-1e100, abs=1e100),
|
||||
dict(rel=-1e100, abs=-1e100),
|
||||
dict(rel=-1e100),
|
||||
dict(abs=-1e100),
|
||||
dict(rel=1e100, abs=-1e100),
|
||||
dict(rel=-1e100, abs=1e100),
|
||||
dict(rel=-1e100, abs=-1e100),
|
||||
]
|
||||
for kwargs in illegal_kwargs:
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -92,10 +93,10 @@ class TestApprox(object):
|
|||
def test_inf_tolerance(self):
|
||||
# Everything should be equal if the tolerance is infinite.
|
||||
large_diffs = [
|
||||
(1, 1000),
|
||||
(1e-50, 1e50),
|
||||
(-1.0, -1e300),
|
||||
(0.0, 10),
|
||||
(1, 1000),
|
||||
(1e-50, 1e50),
|
||||
(-1.0, -1e300),
|
||||
(0.0, 10),
|
||||
]
|
||||
for a, x in large_diffs:
|
||||
assert a != approx(x, rel=0.0, abs=0.0)
|
||||
|
@ -107,8 +108,8 @@ class TestApprox(object):
|
|||
# If the relative tolerance is zero but the expected value is infinite,
|
||||
# the actual tolerance is a NaN, which should be an error.
|
||||
illegal_kwargs = [
|
||||
dict(rel=inf, abs=0.0),
|
||||
dict(rel=inf, abs=inf),
|
||||
dict(rel=inf, abs=0.0),
|
||||
dict(rel=inf, abs=inf),
|
||||
]
|
||||
for kwargs in illegal_kwargs:
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -116,9 +117,9 @@ class TestApprox(object):
|
|||
|
||||
def test_nan_tolerance(self):
|
||||
illegal_kwargs = [
|
||||
dict(rel=nan),
|
||||
dict(abs=nan),
|
||||
dict(rel=nan, abs=nan),
|
||||
dict(rel=nan),
|
||||
dict(abs=nan),
|
||||
dict(rel=nan, abs=nan),
|
||||
]
|
||||
for kwargs in illegal_kwargs:
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -135,15 +136,15 @@ class TestApprox(object):
|
|||
# None of the other tests (except the doctests) should be affected by
|
||||
# the choice of defaults.
|
||||
examples = [
|
||||
# Relative tolerance used.
|
||||
(eq, 1e100 + 1e94, 1e100),
|
||||
(ne, 1e100 + 2e94, 1e100),
|
||||
(eq, 1e0 + 1e-6, 1e0),
|
||||
(ne, 1e0 + 2e-6, 1e0),
|
||||
# Absolute tolerance used.
|
||||
(eq, 1e-100, + 1e-106),
|
||||
(eq, 1e-100, + 2e-106),
|
||||
(eq, 1e-100, 0),
|
||||
# Relative tolerance used.
|
||||
(eq, 1e100 + 1e94, 1e100),
|
||||
(ne, 1e100 + 2e94, 1e100),
|
||||
(eq, 1e0 + 1e-6, 1e0),
|
||||
(ne, 1e0 + 2e-6, 1e0),
|
||||
# Absolute tolerance used.
|
||||
(eq, 1e-100, + 1e-106),
|
||||
(eq, 1e-100, + 2e-106),
|
||||
(eq, 1e-100, 0),
|
||||
]
|
||||
for op, a, x in examples:
|
||||
assert op(a, approx(x))
|
||||
|
@ -166,9 +167,9 @@ class TestApprox(object):
|
|||
|
||||
def test_relative_tolerance(self):
|
||||
within_1e8_rel = [
|
||||
(1e8 + 1e0, 1e8),
|
||||
(1e0 + 1e-8, 1e0),
|
||||
(1e-8 + 1e-16, 1e-8),
|
||||
(1e8 + 1e0, 1e8),
|
||||
(1e0 + 1e-8, 1e0),
|
||||
(1e-8 + 1e-16, 1e-8),
|
||||
]
|
||||
for a, x in within_1e8_rel:
|
||||
assert a == approx(x, rel=5e-8, abs=0.0)
|
||||
|
@ -176,9 +177,9 @@ class TestApprox(object):
|
|||
|
||||
def test_absolute_tolerance(self):
|
||||
within_1e8_abs = [
|
||||
(1e8 + 9e-9, 1e8),
|
||||
(1e0 + 9e-9, 1e0),
|
||||
(1e-8 + 9e-9, 1e-8),
|
||||
(1e8 + 9e-9, 1e8),
|
||||
(1e0 + 9e-9, 1e0),
|
||||
(1e-8 + 9e-9, 1e-8),
|
||||
]
|
||||
for a, x in within_1e8_abs:
|
||||
assert a == approx(x, rel=0, abs=5e-8)
|
||||
|
@ -186,37 +187,37 @@ class TestApprox(object):
|
|||
|
||||
def test_expecting_zero(self):
|
||||
examples = [
|
||||
(ne, 1e-6, 0.0),
|
||||
(ne, -1e-6, 0.0),
|
||||
(eq, 1e-12, 0.0),
|
||||
(eq, -1e-12, 0.0),
|
||||
(ne, 2e-12, 0.0),
|
||||
(ne, -2e-12, 0.0),
|
||||
(ne, inf, 0.0),
|
||||
(ne, nan, 0.0),
|
||||
]
|
||||
(ne, 1e-6, 0.0),
|
||||
(ne, -1e-6, 0.0),
|
||||
(eq, 1e-12, 0.0),
|
||||
(eq, -1e-12, 0.0),
|
||||
(ne, 2e-12, 0.0),
|
||||
(ne, -2e-12, 0.0),
|
||||
(ne, inf, 0.0),
|
||||
(ne, nan, 0.0),
|
||||
]
|
||||
for op, a, x in examples:
|
||||
assert op(a, approx(x, rel=0.0, abs=1e-12))
|
||||
assert op(a, approx(x, rel=1e-6, abs=1e-12))
|
||||
|
||||
def test_expecting_inf(self):
|
||||
examples = [
|
||||
(eq, inf, inf),
|
||||
(eq, -inf, -inf),
|
||||
(ne, inf, -inf),
|
||||
(ne, 0.0, inf),
|
||||
(ne, nan, inf),
|
||||
(eq, inf, inf),
|
||||
(eq, -inf, -inf),
|
||||
(ne, inf, -inf),
|
||||
(ne, 0.0, inf),
|
||||
(ne, nan, inf),
|
||||
]
|
||||
for op, a, x in examples:
|
||||
assert op(a, approx(x))
|
||||
|
||||
def test_expecting_nan(self):
|
||||
examples = [
|
||||
(nan, nan),
|
||||
(-nan, -nan),
|
||||
(nan, -nan),
|
||||
(0.0, nan),
|
||||
(inf, nan),
|
||||
(nan, nan),
|
||||
(-nan, -nan),
|
||||
(nan, -nan),
|
||||
(0.0, nan),
|
||||
(inf, nan),
|
||||
]
|
||||
for a, x in examples:
|
||||
# If there is a relative tolerance and the expected value is NaN,
|
||||
|
@ -230,23 +231,23 @@ class TestApprox(object):
|
|||
|
||||
def test_expecting_sequence(self):
|
||||
within_1e8 = [
|
||||
(1e8 + 1e0, 1e8),
|
||||
(1e0 + 1e-8, 1e0),
|
||||
(1e-8 + 1e-16, 1e-8),
|
||||
(1e8 + 1e0, 1e8),
|
||||
(1e0 + 1e-8, 1e0),
|
||||
(1e-8 + 1e-16, 1e-8),
|
||||
]
|
||||
actual, expected = zip(*within_1e8)
|
||||
assert actual == approx(expected, rel=5e-8, abs=0.0)
|
||||
|
||||
def test_expecting_sequence_wrong_len(self):
|
||||
assert [1, 2] != approx([1])
|
||||
assert [1, 2] != approx([1,2,3])
|
||||
assert [1, 2] != approx([1, 2, 3])
|
||||
|
||||
def test_complex(self):
|
||||
within_1e6 = [
|
||||
( 1.000001 + 1.0j, 1.0 + 1.0j),
|
||||
(1.0 + 1.000001j, 1.0 + 1.0j),
|
||||
(-1.000001 + 1.0j, -1.0 + 1.0j),
|
||||
(1.0 - 1.000001j, 1.0 - 1.0j),
|
||||
(1.000001 + 1.0j, 1.0 + 1.0j),
|
||||
(1.0 + 1.000001j, 1.0 + 1.0j),
|
||||
(-1.000001 + 1.0j, -1.0 + 1.0j),
|
||||
(1.0 - 1.000001j, 1.0 - 1.0j),
|
||||
]
|
||||
for a, x in within_1e6:
|
||||
assert a == approx(x, rel=5e-6, abs=0)
|
||||
|
@ -254,8 +255,8 @@ class TestApprox(object):
|
|||
|
||||
def test_int(self):
|
||||
within_1e6 = [
|
||||
(1000001, 1000000),
|
||||
(-1000001, -1000000),
|
||||
(1000001, 1000000),
|
||||
(-1000001, -1000000),
|
||||
]
|
||||
for a, x in within_1e6:
|
||||
assert a == approx(x, rel=5e-6, abs=0)
|
||||
|
@ -263,8 +264,8 @@ class TestApprox(object):
|
|||
|
||||
def test_decimal(self):
|
||||
within_1e6 = [
|
||||
(Decimal('1.000001'), Decimal('1.0')),
|
||||
(Decimal('-1.000001'), Decimal('-1.0')),
|
||||
(Decimal('1.000001'), Decimal('1.0')),
|
||||
(Decimal('-1.000001'), Decimal('-1.0')),
|
||||
]
|
||||
for a, x in within_1e6:
|
||||
assert a == approx(x, rel=Decimal('5e-6'), abs=0)
|
||||
|
@ -272,8 +273,8 @@ class TestApprox(object):
|
|||
|
||||
def test_fraction(self):
|
||||
within_1e6 = [
|
||||
(1 + Fraction(1, 1000000), Fraction(1)),
|
||||
(-1 - Fraction(-1, 1000000), Fraction(-1)),
|
||||
(1 + Fraction(1, 1000000), Fraction(1)),
|
||||
(-1 - Fraction(-1, 1000000), Fraction(-1)),
|
||||
]
|
||||
for a, x in within_1e6:
|
||||
assert a == approx(x, rel=5e-6, abs=0)
|
||||
|
@ -282,10 +283,10 @@ class TestApprox(object):
|
|||
def test_doctests(self):
|
||||
parser = doctest.DocTestParser()
|
||||
test = parser.get_doctest(
|
||||
approx.__doc__,
|
||||
{'approx': approx},
|
||||
approx.__name__,
|
||||
None, None,
|
||||
approx.__doc__,
|
||||
{'approx': approx},
|
||||
approx.__name__,
|
||||
None, None,
|
||||
)
|
||||
runner = MyDocTestRunner()
|
||||
runner.run(test)
|
||||
|
@ -309,4 +310,3 @@ class TestApprox(object):
|
|||
'*At index 0 diff: 3 != 4 * {0}'.format(expected),
|
||||
'=* 1 failed in *=',
|
||||
])
|
||||
|
||||
|
|
|
@ -419,10 +419,10 @@ class TestFunction(object):
|
|||
pass
|
||||
|
||||
f1 = pytest.Function(name="name", parent=session, config=config,
|
||||
args=(1,), callobj=func1)
|
||||
args=(1,), callobj=func1)
|
||||
assert f1 == f1
|
||||
f2 = pytest.Function(name="name",config=config,
|
||||
callobj=func2, parent=session)
|
||||
f2 = pytest.Function(name="name", config=config,
|
||||
callobj=func2, parent=session)
|
||||
assert f1 != f2
|
||||
|
||||
def test_issue197_parametrize_emptyset(self, testdir):
|
||||
|
@ -476,7 +476,6 @@ class TestFunction(object):
|
|||
rec = testdir.inline_run()
|
||||
rec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
def test_parametrize_with_non_hashable_values_indirect(self, testdir):
|
||||
"""Test parametrization with non-hashable values with indirect parametrization."""
|
||||
testdir.makepyfile("""
|
||||
|
@ -504,7 +503,6 @@ class TestFunction(object):
|
|||
rec = testdir.inline_run()
|
||||
rec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
def test_parametrize_overrides_fixture(self, testdir):
|
||||
"""Test parametrization when parameter overrides existing fixture with same name."""
|
||||
testdir.makepyfile("""
|
||||
|
@ -532,7 +530,6 @@ class TestFunction(object):
|
|||
rec = testdir.inline_run()
|
||||
rec.assertoutcome(passed=3)
|
||||
|
||||
|
||||
def test_parametrize_overrides_parametrized_fixture(self, testdir):
|
||||
"""Test parametrization when parameter overrides existing parametrized fixture with same name."""
|
||||
testdir.makepyfile("""
|
||||
|
@ -733,11 +730,11 @@ class TestSorting(object):
|
|||
assert not (fn1 == fn3)
|
||||
assert fn1 != fn3
|
||||
|
||||
for fn in fn1,fn2,fn3:
|
||||
for fn in fn1, fn2, fn3:
|
||||
assert fn != 3
|
||||
assert fn != modcol
|
||||
assert fn != [1,2,3]
|
||||
assert [1,2,3] != fn
|
||||
assert fn != [1, 2, 3]
|
||||
assert [1, 2, 3] != fn
|
||||
assert modcol != fn
|
||||
|
||||
def test_allow_sane_sorting_for_decorators(self, testdir):
|
||||
|
@ -838,7 +835,7 @@ class TestConftestCustomization(object):
|
|||
modcol = testdir.getmodulecol("def _hello(): pass")
|
||||
l = []
|
||||
monkeypatch.setattr(pytest.Module, 'makeitem',
|
||||
lambda self, name, obj: l.append(name))
|
||||
lambda self, name, obj: l.append(name))
|
||||
l = modcol.collect()
|
||||
assert '_hello' not in l
|
||||
|
||||
|
@ -870,6 +867,7 @@ class TestConftestCustomization(object):
|
|||
result = testdir.runpytest_subprocess()
|
||||
result.stdout.fnmatch_lines('*1 passed*')
|
||||
|
||||
|
||||
def test_setup_only_available_in_subdir(testdir):
|
||||
sub1 = testdir.mkpydir("sub1")
|
||||
sub2 = testdir.mkpydir("sub2")
|
||||
|
@ -896,6 +894,7 @@ def test_setup_only_available_in_subdir(testdir):
|
|||
result = testdir.runpytest("-v", "-s")
|
||||
result.assert_outcomes(passed=2)
|
||||
|
||||
|
||||
def test_modulecol_roundtrip(testdir):
|
||||
modcol = testdir.getmodulecol("pass", withinit=True)
|
||||
trail = modcol.nodeid
|
||||
|
@ -923,13 +922,13 @@ class TestTracebackCutting(object):
|
|||
out = result.stdout.str()
|
||||
assert "xyz" in out
|
||||
assert "conftest.py:5: ValueError" in out
|
||||
numentries = out.count("_ _ _") # separator for traceback entries
|
||||
numentries = out.count("_ _ _") # separator for traceback entries
|
||||
assert numentries == 0
|
||||
|
||||
result = testdir.runpytest("--fulltrace", p)
|
||||
out = result.stdout.str()
|
||||
assert "conftest.py:5: ValueError" in out
|
||||
numentries = out.count("_ _ _ _") # separator for traceback entries
|
||||
numentries = out.count("_ _ _ _") # separator for traceback entries
|
||||
assert numentries > 3
|
||||
|
||||
def test_traceback_error_during_import(self, testdir):
|
||||
|
@ -1180,6 +1179,7 @@ def test_collector_attributes(testdir):
|
|||
"*1 passed*",
|
||||
])
|
||||
|
||||
|
||||
def test_customize_through_attributes(testdir):
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
|
@ -1349,7 +1349,6 @@ def test_skip_duplicates_by_default(testdir):
|
|||
])
|
||||
|
||||
|
||||
|
||||
def test_keep_duplicates(testdir):
|
||||
"""Test for issue https://github.com/pytest-dev/pytest/issues/1609 (#1609)
|
||||
|
||||
|
|
|
@ -7,17 +7,22 @@ from _pytest.pytester import get_public_names
|
|||
from _pytest.fixtures import FixtureLookupError
|
||||
from _pytest import fixtures
|
||||
|
||||
|
||||
def test_getfuncargnames():
|
||||
def f(): pass
|
||||
def f():
|
||||
pass
|
||||
assert not fixtures.getfuncargnames(f)
|
||||
|
||||
def g(arg): pass
|
||||
def g(arg):
|
||||
pass
|
||||
assert fixtures.getfuncargnames(g) == ('arg',)
|
||||
|
||||
def h(arg1, arg2="hello"): pass
|
||||
def h(arg1, arg2="hello"):
|
||||
pass
|
||||
assert fixtures.getfuncargnames(h) == ('arg1',)
|
||||
|
||||
def h(arg1, arg2, arg3="hello"): pass
|
||||
def h(arg1, arg2, arg3="hello"):
|
||||
pass
|
||||
assert fixtures.getfuncargnames(h) == ('arg1', 'arg2')
|
||||
|
||||
class A(object):
|
||||
|
@ -25,9 +30,10 @@ def test_getfuncargnames():
|
|||
pass
|
||||
|
||||
assert fixtures.getfuncargnames(A().f) == ('arg1',)
|
||||
if sys.version_info < (3,0):
|
||||
if sys.version_info < (3, 0):
|
||||
assert fixtures.getfuncargnames(A.f) == ('arg1',)
|
||||
|
||||
|
||||
class TestFillFixtures(object):
|
||||
def test_fillfuncargs_exposed(self):
|
||||
# used by oejskit, kept for compatibility
|
||||
|
@ -44,7 +50,7 @@ class TestFillFixtures(object):
|
|||
def test_func(some):
|
||||
pass
|
||||
""")
|
||||
result = testdir.runpytest() # "--collect-only")
|
||||
result = testdir.runpytest() # "--collect-only")
|
||||
assert result.ret != 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*def test_func(some)*",
|
||||
|
@ -439,7 +445,6 @@ class TestFillFixtures(object):
|
|||
])
|
||||
assert "INTERNAL" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_fixture_excinfo_leak(self, testdir):
|
||||
# on python2 sys.excinfo would leak into fixture executions
|
||||
testdir.makepyfile("""
|
||||
|
@ -551,7 +556,8 @@ class TestRequestBasic(object):
|
|||
else:
|
||||
# see #1830 for a cleaner way to accomplish this
|
||||
@contextlib.contextmanager
|
||||
def expecting_no_warning(): yield
|
||||
def expecting_no_warning():
|
||||
yield
|
||||
|
||||
warning_expectation = expecting_no_warning()
|
||||
|
||||
|
@ -639,7 +645,6 @@ class TestRequestBasic(object):
|
|||
mod = reprec.getcalls("pytest_runtest_setup")[0].item.module
|
||||
assert not mod.l
|
||||
|
||||
|
||||
def test_request_addfinalizer_partial_setup_failure(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -655,7 +660,7 @@ class TestRequestBasic(object):
|
|||
result = testdir.runpytest(p)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*1 error*" # XXX the whole module collection fails
|
||||
])
|
||||
])
|
||||
|
||||
def test_request_subrequest_addfinalizer_exceptions(self, testdir):
|
||||
"""
|
||||
|
@ -815,9 +820,10 @@ class TestRequestBasic(object):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
class TestRequestMarking(object):
|
||||
def test_applymarker(self, testdir):
|
||||
item1,item2 = testdir.getitems("""
|
||||
item1, item2 = testdir.getitems("""
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -875,6 +881,7 @@ class TestRequestMarking(object):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
class TestRequestCachedSetup(object):
|
||||
def test_request_cachedsetup_defaultmodule(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
|
@ -1040,6 +1047,7 @@ class TestRequestCachedSetup(object):
|
|||
"*ZeroDivisionError*",
|
||||
])
|
||||
|
||||
|
||||
class TestFixtureUsages(object):
|
||||
def test_noargfixturedec(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -1297,7 +1305,7 @@ class TestFixtureUsages(object):
|
|||
reprec = testdir.inline_run("-v")
|
||||
reprec.assertoutcome(passed=4)
|
||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
||||
assert l == [1,2, 10,20]
|
||||
assert l == [1, 2, 10, 20]
|
||||
|
||||
|
||||
class TestFixtureManagerParseFactories(object):
|
||||
|
@ -1598,8 +1606,6 @@ class TestAutouseManagement(object):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
|
||||
def test_funcarg_and_setup(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -1706,7 +1712,7 @@ class TestAutouseManagement(object):
|
|||
pass
|
||||
""")
|
||||
confcut = "--confcutdir={0}".format(testdir.tmpdir)
|
||||
reprec = testdir.inline_run("-v","-s", confcut)
|
||||
reprec = testdir.inline_run("-v", "-s", confcut)
|
||||
reprec.assertoutcome(passed=8)
|
||||
config = reprec.getcalls("pytest_unconfigure")[0].config
|
||||
l = config.pluginmanager._getconftestmodules(p)[0].l
|
||||
|
@ -1776,8 +1782,8 @@ class TestAutouseManagement(object):
|
|||
reprec.assertoutcome(passed=1)
|
||||
|
||||
@pytest.mark.issue226
|
||||
@pytest.mark.parametrize("param1", ["", "params=[1]"], ids=["p00","p01"])
|
||||
@pytest.mark.parametrize("param2", ["", "params=[1]"], ids=["p10","p11"])
|
||||
@pytest.mark.parametrize("param1", ["", "params=[1]"], ids=["p00", "p01"])
|
||||
@pytest.mark.parametrize("param2", ["", "params=[1]"], ids=["p10", "p11"])
|
||||
def test_ordering_dependencies_torndown_first(self, testdir, param1, param2):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -2108,7 +2114,7 @@ class TestFixtureMarker(object):
|
|||
reprec = testdir.inline_run("-v")
|
||||
reprec.assertoutcome(passed=4)
|
||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
||||
assert l == [1,1,2,2]
|
||||
assert l == [1, 1, 2, 2]
|
||||
|
||||
def test_module_parametrized_ordering(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
|
@ -2243,7 +2249,7 @@ class TestFixtureMarker(object):
|
|||
'fin:mod1', 'create:mod2', 'test2', 'create:1', 'test3',
|
||||
'fin:1', 'create:2', 'test3', 'fin:2', 'create:1',
|
||||
'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
|
||||
'fin:mod2']
|
||||
'fin:mod2']
|
||||
import pprint
|
||||
pprint.pprint(list(zip(l, expected)))
|
||||
assert l == expected
|
||||
|
@ -2351,7 +2357,7 @@ class TestFixtureMarker(object):
|
|||
""")
|
||||
reprec = testdir.inline_run("-s")
|
||||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
||||
assert l == [1,2]
|
||||
assert l == [1, 2]
|
||||
|
||||
def test_parametrize_separated_lifecycle(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -2373,7 +2379,7 @@ class TestFixtureMarker(object):
|
|||
l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
|
||||
import pprint
|
||||
pprint.pprint(l)
|
||||
#assert len(l) == 6
|
||||
# assert len(l) == 6
|
||||
assert l[0] == l[1] == 1
|
||||
assert l[2] == "fin1"
|
||||
assert l[3] == l[4] == 2
|
||||
|
@ -2401,7 +2407,6 @@ class TestFixtureMarker(object):
|
|||
reprec = testdir.inline_run("-v")
|
||||
reprec.assertoutcome(passed=5)
|
||||
|
||||
|
||||
@pytest.mark.issue246
|
||||
@pytest.mark.parametrize("scope", ["session", "function", "module"])
|
||||
def test_finalizer_order_on_parametrization(self, scope, testdir):
|
||||
|
@ -2544,7 +2549,7 @@ class TestFixtureMarker(object):
|
|||
|
||||
|
||||
class TestRequestScopeAccess(object):
|
||||
pytestmark = pytest.mark.parametrize(("scope", "ok", "error"),[
|
||||
pytestmark = pytest.mark.parametrize(("scope", "ok", "error"), [
|
||||
["session", "", "fspath class function module"],
|
||||
["module", "module fspath", "cls function"],
|
||||
["class", "module fspath cls", "function"],
|
||||
|
@ -2565,7 +2570,7 @@ class TestRequestScopeAccess(object):
|
|||
assert request.config
|
||||
def test_func():
|
||||
pass
|
||||
""" %(scope, ok.split(), error.split()))
|
||||
""" % (scope, ok.split(), error.split()))
|
||||
reprec = testdir.inline_run("-l")
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
@ -2583,10 +2588,11 @@ class TestRequestScopeAccess(object):
|
|||
assert request.config
|
||||
def test_func(arg):
|
||||
pass
|
||||
""" %(scope, ok.split(), error.split()))
|
||||
""" % (scope, ok.split(), error.split()))
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
class TestErrors(object):
|
||||
def test_subfactory_missing_funcarg(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -2632,8 +2638,6 @@ class TestErrors(object):
|
|||
*3 pass*2 error*
|
||||
""")
|
||||
|
||||
|
||||
|
||||
def test_setupfunc_missing_funcarg(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -2651,6 +2655,7 @@ class TestErrors(object):
|
|||
"*1 error*",
|
||||
])
|
||||
|
||||
|
||||
class TestShowFixtures(object):
|
||||
def test_funcarg_compat(self, testdir):
|
||||
config = testdir.parseconfigure("--funcargs")
|
||||
|
@ -2659,18 +2664,16 @@ class TestShowFixtures(object):
|
|||
def test_show_fixtures(self, testdir):
|
||||
result = testdir.runpytest("--fixtures")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*tmpdir*",
|
||||
"*temporary directory*",
|
||||
]
|
||||
)
|
||||
"*tmpdir*",
|
||||
"*temporary directory*",
|
||||
])
|
||||
|
||||
def test_show_fixtures_verbose(self, testdir):
|
||||
result = testdir.runpytest("--fixtures", "-v")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*tmpdir*--*tmpdir.py*",
|
||||
"*temporary directory*",
|
||||
]
|
||||
)
|
||||
"*tmpdir*--*tmpdir.py*",
|
||||
"*temporary directory*",
|
||||
])
|
||||
|
||||
def test_show_fixtures_testmodule(self, testdir):
|
||||
p = testdir.makepyfile('''
|
||||
|
@ -2799,7 +2802,6 @@ class TestShowFixtures(object):
|
|||
indented line
|
||||
"""))
|
||||
|
||||
|
||||
def test_show_fixtures_different_files(self, testdir):
|
||||
"""
|
||||
#833: --fixtures only shows fixtures from first file
|
||||
|
@ -2978,6 +2980,7 @@ class TestContextManagerFixtureFuncs(object):
|
|||
result = testdir.runpytest("-s")
|
||||
result.stdout.fnmatch_lines("*mew*")
|
||||
|
||||
|
||||
class TestParameterizedSubRequest(object):
|
||||
def test_call_from_fixture(self, testdir):
|
||||
testfile = testdir.makepyfile("""
|
||||
|
@ -3083,6 +3086,3 @@ class TestParameterizedSubRequest(object):
|
|||
E*{1}:5
|
||||
*1 failed*
|
||||
""".format(fixfile.strpath, testfile.basename))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ from _pytest import runner
|
|||
|
||||
|
||||
class TestOEJSKITSpecials(object):
|
||||
def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
|
||||
def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
|
@ -30,7 +30,7 @@ class TestOEJSKITSpecials(object):
|
|||
pytest._fillfuncargs(clscol)
|
||||
assert clscol.funcargs['arg1'] == 42
|
||||
|
||||
def test_autouse_fixture(self, testdir): # rough jstests usage
|
||||
def test_autouse_fixture(self, testdir): # rough jstests usage
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
|
@ -76,6 +76,7 @@ def test_wrapped_getfslineno():
|
|||
fs2, lineno2 = python.getfslineno(wrap)
|
||||
assert lineno > lineno2, "getfslineno does not unwrap correctly"
|
||||
|
||||
|
||||
class TestMockDecoration(object):
|
||||
def test_wrapped_getfuncargnames(self):
|
||||
from _pytest.compat import getfuncargnames
|
||||
|
@ -173,7 +174,7 @@ class TestMockDecoration(object):
|
|||
reprec.assertoutcome(passed=2)
|
||||
calls = reprec.getcalls("pytest_runtest_logreport")
|
||||
funcnames = [call.report.location[2] for call in calls
|
||||
if call.report.when == "call"]
|
||||
if call.report.when == "call"]
|
||||
assert funcnames == ["T.test_hello", "test_someting"]
|
||||
|
||||
def test_mock_sorting(self, testdir):
|
||||
|
@ -246,6 +247,7 @@ class TestReRunTests(object):
|
|||
*2 passed*
|
||||
""")
|
||||
|
||||
|
||||
def test_pytestconfig_is_session_scoped():
|
||||
from _pytest.fixtures import pytestconfig
|
||||
assert pytestconfig._pytestfixturefunction.scope == "session"
|
||||
|
|
|
@ -29,13 +29,15 @@ class TestMetafunc(object):
|
|||
return python.Metafunc(func, fixtureinfo, None)
|
||||
|
||||
def test_no_funcargs(self, testdir):
|
||||
def function(): pass
|
||||
def function():
|
||||
pass
|
||||
metafunc = self.Metafunc(function)
|
||||
assert not metafunc.fixturenames
|
||||
repr(metafunc._calls)
|
||||
|
||||
def test_function_basic(self):
|
||||
def func(arg1, arg2="qwe"): pass
|
||||
def func(arg1, arg2="qwe"):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
assert len(metafunc.fixturenames) == 1
|
||||
assert 'arg1' in metafunc.fixturenames
|
||||
|
@ -43,7 +45,8 @@ class TestMetafunc(object):
|
|||
assert metafunc.cls is None
|
||||
|
||||
def test_addcall_no_args(self):
|
||||
def func(arg1): pass
|
||||
def func(arg1):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.addcall()
|
||||
assert len(metafunc._calls) == 1
|
||||
|
@ -52,7 +55,8 @@ class TestMetafunc(object):
|
|||
assert not hasattr(call, 'param')
|
||||
|
||||
def test_addcall_id(self):
|
||||
def func(arg1): pass
|
||||
def func(arg1):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
pytest.raises(ValueError, "metafunc.addcall(id=None)")
|
||||
|
||||
|
@ -65,10 +69,12 @@ class TestMetafunc(object):
|
|||
assert metafunc._calls[1].id == "2"
|
||||
|
||||
def test_addcall_param(self):
|
||||
def func(arg1): pass
|
||||
def func(arg1):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
|
||||
class obj(object): pass
|
||||
class obj(object):
|
||||
pass
|
||||
|
||||
metafunc.addcall(param=obj)
|
||||
metafunc.addcall(param=obj)
|
||||
|
@ -79,11 +85,13 @@ class TestMetafunc(object):
|
|||
assert metafunc._calls[2].getparam("arg1") == 1
|
||||
|
||||
def test_addcall_funcargs(self):
|
||||
def func(x): pass
|
||||
def func(x):
|
||||
pass
|
||||
|
||||
metafunc = self.Metafunc(func)
|
||||
|
||||
class obj(object): pass
|
||||
class obj(object):
|
||||
pass
|
||||
|
||||
metafunc.addcall(funcargs={"x": 2})
|
||||
metafunc.addcall(funcargs={"x": 3})
|
||||
|
@ -94,17 +102,19 @@ class TestMetafunc(object):
|
|||
assert not hasattr(metafunc._calls[1], 'param')
|
||||
|
||||
def test_parametrize_error(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize("x", [1,2])
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6]))
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6]))
|
||||
metafunc.parametrize("y", [1,2])
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
|
||||
metafunc.parametrize("x", [1, 2])
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6]))
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6]))
|
||||
metafunc.parametrize("y", [1, 2])
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
||||
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
||||
|
||||
def test_parametrize_bad_scope(self, testdir):
|
||||
def func(x): pass
|
||||
def func(x):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
try:
|
||||
metafunc.parametrize("x", [1], scope='doggy')
|
||||
|
@ -112,42 +122,47 @@ class TestMetafunc(object):
|
|||
assert "has an unsupported scope value 'doggy'" in str(ve)
|
||||
|
||||
def test_parametrize_and_id(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
|
||||
metafunc.parametrize("x", [1,2], ids=['basic', 'advanced'])
|
||||
metafunc.parametrize("x", [1, 2], ids=['basic', 'advanced'])
|
||||
metafunc.parametrize("y", ["abc", "def"])
|
||||
ids = [x.id for x in metafunc._calls]
|
||||
assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"]
|
||||
|
||||
def test_parametrize_and_id_unicode(self):
|
||||
"""Allow unicode strings for "ids" parameter in Python 2 (##1905)"""
|
||||
def func(x): pass
|
||||
def func(x):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize("x", [1, 2], ids=[u'basic', u'advanced'])
|
||||
ids = [x.id for x in metafunc._calls]
|
||||
assert ids == [u"basic", u"advanced"]
|
||||
|
||||
def test_parametrize_with_wrong_number_of_ids(self, testdir):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
|
||||
pytest.raises(ValueError, lambda:
|
||||
metafunc.parametrize("x", [1,2], ids=['basic']))
|
||||
metafunc.parametrize("x", [1, 2], ids=['basic']))
|
||||
|
||||
pytest.raises(ValueError, lambda:
|
||||
metafunc.parametrize(("x","y"), [("abc", "def"),
|
||||
("ghi", "jkl")], ids=["one"]))
|
||||
metafunc.parametrize(("x", "y"), [("abc", "def"),
|
||||
("ghi", "jkl")], ids=["one"]))
|
||||
|
||||
@pytest.mark.issue510
|
||||
def test_parametrize_empty_list(self):
|
||||
def func( y): pass
|
||||
def func(y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize("y", [])
|
||||
assert 'skip' in metafunc._calls[0].keywords
|
||||
|
||||
def test_parametrize_with_userobjects(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
|
||||
class A(object):
|
||||
|
@ -178,11 +193,27 @@ class TestMetafunc(object):
|
|||
"""
|
||||
from _pytest.python import _idval
|
||||
values = [
|
||||
(u'', ''),
|
||||
(u'ascii', 'ascii'),
|
||||
(u'ação', 'a\\xe7\\xe3o'),
|
||||
(u'josé@blah.com', 'jos\\xe9@blah.com'),
|
||||
(u'δοκ.ιμή@παράδειγμα.δοκιμή', '\\u03b4\\u03bf\\u03ba.\\u03b9\\u03bc\\u03ae@\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3\\u03bc\\u03b1.\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae'),
|
||||
(
|
||||
u'',
|
||||
''
|
||||
),
|
||||
(
|
||||
u'ascii',
|
||||
'ascii'
|
||||
),
|
||||
(
|
||||
u'ação',
|
||||
'a\\xe7\\xe3o'
|
||||
),
|
||||
(
|
||||
u'josé@blah.com',
|
||||
'jos\\xe9@blah.com'
|
||||
),
|
||||
(
|
||||
u'δοκ.ιμή@παράδειγμα.δοκιμή',
|
||||
'\\u03b4\\u03bf\\u03ba.\\u03b9\\u03bc\\u03ae@\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3'
|
||||
'\\u03bc\\u03b1.\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae'
|
||||
),
|
||||
]
|
||||
for val, expected in values:
|
||||
assert _idval(val, 'a', 6, None) == expected
|
||||
|
@ -279,7 +310,7 @@ class TestMetafunc(object):
|
|||
assert result == ["10.0-IndexError()",
|
||||
"20-KeyError()",
|
||||
"three-b2",
|
||||
]
|
||||
]
|
||||
|
||||
@pytest.mark.issue351
|
||||
def test_idmaker_idfn_unique_names(self):
|
||||
|
@ -291,11 +322,11 @@ class TestMetafunc(object):
|
|||
result = idmaker(("a", "b"), [pytest.param(10.0, IndexError()),
|
||||
pytest.param(20, KeyError()),
|
||||
pytest.param("three", [1, 2, 3]),
|
||||
], idfn=ids)
|
||||
], idfn=ids)
|
||||
assert result == ["a-a0",
|
||||
"a-a1",
|
||||
"a-a2",
|
||||
]
|
||||
]
|
||||
|
||||
@pytest.mark.issue351
|
||||
def test_idmaker_idfn_exception(self):
|
||||
|
@ -331,7 +362,6 @@ class TestMetafunc(object):
|
|||
"\nUpdate your code as this will raise an error in pytest-4.0.",
|
||||
]
|
||||
|
||||
|
||||
def test_parametrize_ids_exception(self, testdir):
|
||||
"""
|
||||
:param testdir: the instance of Testdir class, a temporary
|
||||
|
@ -371,15 +401,16 @@ class TestMetafunc(object):
|
|||
|
||||
def test_idmaker_with_ids_unique_names(self):
|
||||
from _pytest.python import idmaker
|
||||
result = idmaker(("a"), map(pytest.param, [1,2,3,4,5]),
|
||||
result = idmaker(("a"), map(pytest.param, [1, 2, 3, 4, 5]),
|
||||
ids=["a", "a", "b", "c", "b"])
|
||||
assert result == ["a0", "a1", "b0", "c", "b1"]
|
||||
|
||||
def test_addcall_and_parametrize(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.addcall({'x': 1})
|
||||
metafunc.parametrize('y', [2,3])
|
||||
metafunc.parametrize('y', [2, 3])
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == {'x': 1, 'y': 2}
|
||||
assert metafunc._calls[1].funcargs == {'x': 1, 'y': 3}
|
||||
|
@ -388,19 +419,21 @@ class TestMetafunc(object):
|
|||
|
||||
@pytest.mark.issue714
|
||||
def test_parametrize_indirect(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize('x', [1], indirect=True)
|
||||
metafunc.parametrize('y', [2,3], indirect=True)
|
||||
metafunc.parametrize('y', [2, 3], indirect=True)
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == {}
|
||||
assert metafunc._calls[1].funcargs == {}
|
||||
assert metafunc._calls[0].params == dict(x=1,y=2)
|
||||
assert metafunc._calls[1].params == dict(x=1,y=3)
|
||||
assert metafunc._calls[0].params == dict(x=1, y=2)
|
||||
assert metafunc._calls[1].params == dict(x=1, y=3)
|
||||
|
||||
@pytest.mark.issue714
|
||||
def test_parametrize_indirect_list(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize('x, y', [('a', 'b')], indirect=['x'])
|
||||
assert metafunc._calls[0].funcargs == dict(y='b')
|
||||
|
@ -408,7 +441,8 @@ class TestMetafunc(object):
|
|||
|
||||
@pytest.mark.issue714
|
||||
def test_parametrize_indirect_list_all(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'y'])
|
||||
assert metafunc._calls[0].funcargs == {}
|
||||
|
@ -416,7 +450,8 @@ class TestMetafunc(object):
|
|||
|
||||
@pytest.mark.issue714
|
||||
def test_parametrize_indirect_list_empty(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize('x, y', [('a', 'b')], indirect=[])
|
||||
assert metafunc._calls[0].funcargs == dict(x='a', y='b')
|
||||
|
@ -454,7 +489,8 @@ class TestMetafunc(object):
|
|||
|
||||
@pytest.mark.issue714
|
||||
def test_parametrize_indirect_list_error(self, testdir):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
with pytest.raises(ValueError):
|
||||
metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'z'])
|
||||
|
@ -550,16 +586,17 @@ class TestMetafunc(object):
|
|||
])
|
||||
|
||||
def test_addcalls_and_parametrize_indirect(self):
|
||||
def func(x, y): pass
|
||||
def func(x, y):
|
||||
pass
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.addcall(param="123")
|
||||
metafunc.parametrize('x', [1], indirect=True)
|
||||
metafunc.parametrize('y', [2,3], indirect=True)
|
||||
metafunc.parametrize('y', [2, 3], indirect=True)
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == {}
|
||||
assert metafunc._calls[1].funcargs == {}
|
||||
assert metafunc._calls[0].params == dict(x=1,y=2)
|
||||
assert metafunc._calls[1].params == dict(x=1,y=3)
|
||||
assert metafunc._calls[0].params == dict(x=1, y=2)
|
||||
assert metafunc._calls[1].params == dict(x=1, y=3)
|
||||
|
||||
def test_parametrize_functional(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -584,7 +621,7 @@ class TestMetafunc(object):
|
|||
|
||||
def test_parametrize_onearg(self):
|
||||
metafunc = self.Metafunc(lambda x: None)
|
||||
metafunc.parametrize("x", [1,2])
|
||||
metafunc.parametrize("x", [1, 2])
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == dict(x=1)
|
||||
assert metafunc._calls[0].id == "1"
|
||||
|
@ -593,15 +630,15 @@ class TestMetafunc(object):
|
|||
|
||||
def test_parametrize_onearg_indirect(self):
|
||||
metafunc = self.Metafunc(lambda x: None)
|
||||
metafunc.parametrize("x", [1,2], indirect=True)
|
||||
metafunc.parametrize("x", [1, 2], indirect=True)
|
||||
assert metafunc._calls[0].params == dict(x=1)
|
||||
assert metafunc._calls[0].id == "1"
|
||||
assert metafunc._calls[1].params == dict(x=2)
|
||||
assert metafunc._calls[1].id == "2"
|
||||
|
||||
def test_parametrize_twoargs(self):
|
||||
metafunc = self.Metafunc(lambda x,y: None)
|
||||
metafunc.parametrize(("x", "y"), [(1,2), (3,4)])
|
||||
metafunc = self.Metafunc(lambda x, y: None)
|
||||
metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)])
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == dict(x=1, y=2)
|
||||
assert metafunc._calls[0].id == "1-2"
|
||||
|
@ -672,16 +709,20 @@ class TestMetafunc(object):
|
|||
""")
|
||||
|
||||
def test_format_args(self):
|
||||
def function1(): pass
|
||||
def function1():
|
||||
pass
|
||||
assert fixtures._format_args(function1) == '()'
|
||||
|
||||
def function2(arg1): pass
|
||||
def function2(arg1):
|
||||
pass
|
||||
assert fixtures._format_args(function2) == "(arg1)"
|
||||
|
||||
def function3(arg1, arg2="qwe"): pass
|
||||
def function3(arg1, arg2="qwe"):
|
||||
pass
|
||||
assert fixtures._format_args(function3) == "(arg1, arg2='qwe')"
|
||||
|
||||
def function4(arg1, *args, **kwargs): pass
|
||||
def function4(arg1, *args, **kwargs):
|
||||
pass
|
||||
assert fixtures._format_args(function4) == "(arg1, *args, **kwargs)"
|
||||
|
||||
|
||||
|
@ -776,7 +817,6 @@ class TestMetafuncFunctional(object):
|
|||
result = testdir.runpytest(p)
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
|
||||
def test_generate_plugin_and_module(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_generate_tests(metafunc):
|
||||
|
@ -1114,7 +1154,7 @@ class TestMetafuncFunctional(object):
|
|||
|
||||
@pytest.mark.issue463
|
||||
@pytest.mark.parametrize('attr', ['parametrise', 'parameterize',
|
||||
'parameterise'])
|
||||
'parameterise'])
|
||||
def test_parametrize_misspelling(self, testdir, attr):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -1251,6 +1291,7 @@ class TestMetafuncFunctionalAuto(object):
|
|||
|
||||
class TestMarkersWithParametrization(object):
|
||||
pytestmark = pytest.mark.issue308
|
||||
|
||||
def test_simple_mark(self, testdir):
|
||||
s = """
|
||||
import pytest
|
||||
|
@ -1434,7 +1475,6 @@ class TestMarkersWithParametrization(object):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=2, skipped=2)
|
||||
|
||||
|
||||
@pytest.mark.issue290
|
||||
def test_parametrize_ID_generation_string_int_works(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -1451,7 +1491,6 @@ class TestMarkersWithParametrization(object):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('strict', [True, False])
|
||||
def test_parametrize_marked_value(self, testdir, strict):
|
||||
s = """
|
||||
|
@ -1475,7 +1514,6 @@ class TestMarkersWithParametrization(object):
|
|||
passed, failed = (0, 2) if strict else (2, 0)
|
||||
reprec.assertoutcome(passed=passed, failed=failed)
|
||||
|
||||
|
||||
def test_pytest_make_parametrize_id(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_make_parametrize_id(config, val):
|
||||
|
|
|
@ -118,7 +118,6 @@ class TestRaises(object):
|
|||
for o in gc.get_objects():
|
||||
assert type(o) is not T
|
||||
|
||||
|
||||
def test_raises_match(self):
|
||||
msg = r"with base \d+"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
import py, pytest
|
||||
import py
|
||||
import pytest
|
||||
|
||||
# test for _argcomplete but not specific for any application
|
||||
|
||||
|
||||
def equal_with_bash(prefix, ffc, fc, out=None):
|
||||
res = ffc(prefix)
|
||||
res_bash = set(fc(prefix))
|
||||
|
@ -17,10 +19,12 @@ def equal_with_bash(prefix, ffc, fc, out=None):
|
|||
# copied from argcomplete.completers as import from there
|
||||
# also pulls in argcomplete.__init__ which opens filedescriptor 9
|
||||
# this gives an IOError at the end of testrun
|
||||
|
||||
|
||||
def _wrapcall(*args, **kargs):
|
||||
try:
|
||||
if py.std.sys.version_info > (2,7):
|
||||
return py.std.subprocess.check_output(*args,**kargs).decode().splitlines()
|
||||
if py.std.sys.version_info > (2, 7):
|
||||
return py.std.subprocess.check_output(*args, **kargs).decode().splitlines()
|
||||
if 'stdout' in kargs:
|
||||
raise ValueError('stdout argument not allowed, it will be overridden.')
|
||||
process = py.std.subprocess.Popen(
|
||||
|
@ -36,9 +40,11 @@ def _wrapcall(*args, **kargs):
|
|||
except py.std.subprocess.CalledProcessError:
|
||||
return []
|
||||
|
||||
|
||||
class FilesCompleter(object):
|
||||
'File completer class, optionally takes a list of allowed extensions'
|
||||
def __init__(self,allowednames=(),directories=True):
|
||||
|
||||
def __init__(self, allowednames=(), directories=True):
|
||||
# Fix if someone passes in a string instead of a list
|
||||
if type(allowednames) is str:
|
||||
allowednames = [allowednames]
|
||||
|
@ -50,25 +56,26 @@ class FilesCompleter(object):
|
|||
completion = []
|
||||
if self.allowednames:
|
||||
if self.directories:
|
||||
files = _wrapcall(['bash','-c',
|
||||
"compgen -A directory -- '{p}'".format(p=prefix)])
|
||||
completion += [ f + '/' for f in files]
|
||||
files = _wrapcall(['bash', '-c',
|
||||
"compgen -A directory -- '{p}'".format(p=prefix)])
|
||||
completion += [f + '/' for f in files]
|
||||
for x in self.allowednames:
|
||||
completion += _wrapcall(['bash', '-c',
|
||||
"compgen -A file -X '!*.{0}' -- '{p}'".format(x,p=prefix)])
|
||||
"compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix)])
|
||||
else:
|
||||
completion += _wrapcall(['bash', '-c',
|
||||
"compgen -A file -- '{p}'".format(p=prefix)])
|
||||
"compgen -A file -- '{p}'".format(p=prefix)])
|
||||
|
||||
anticomp = _wrapcall(['bash', '-c',
|
||||
"compgen -A directory -- '{p}'".format(p=prefix)])
|
||||
"compgen -A directory -- '{p}'".format(p=prefix)])
|
||||
|
||||
completion = list( set(completion) - set(anticomp))
|
||||
completion = list(set(completion) - set(anticomp))
|
||||
|
||||
if self.directories:
|
||||
completion += [f + '/' for f in anticomp]
|
||||
return completion
|
||||
|
||||
|
||||
class TestArgComplete(object):
|
||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||
def test_compare_with_compgen(self):
|
||||
|
|
|
@ -283,6 +283,7 @@ class TestBinReprIntegration(object):
|
|||
"*test_check*PASS*",
|
||||
])
|
||||
|
||||
|
||||
def callequal(left, right, verbose=False):
|
||||
config = mock_config()
|
||||
config.verbose = verbose
|
||||
|
@ -303,15 +304,15 @@ class TestAssert_reprcompare(object):
|
|||
assert '+ eggs' in diff
|
||||
|
||||
def test_text_skipping(self):
|
||||
lines = callequal('a'*50 + 'spam', 'a'*50 + 'eggs')
|
||||
lines = callequal('a' * 50 + 'spam', 'a' * 50 + 'eggs')
|
||||
assert 'Skipping' in lines[1]
|
||||
for line in lines:
|
||||
assert 'a'*50 not in line
|
||||
assert 'a' * 50 not in line
|
||||
|
||||
def test_text_skipping_verbose(self):
|
||||
lines = callequal('a'*50 + 'spam', 'a'*50 + 'eggs', verbose=True)
|
||||
assert '- ' + 'a'*50 + 'spam' in lines
|
||||
assert '+ ' + 'a'*50 + 'eggs' in lines
|
||||
lines = callequal('a' * 50 + 'spam', 'a' * 50 + 'eggs', verbose=True)
|
||||
assert '- ' + 'a' * 50 + 'spam' in lines
|
||||
assert '+ ' + 'a' * 50 + 'eggs' in lines
|
||||
|
||||
def test_multiline_text_diff(self):
|
||||
left = 'foo\nspam\nbar'
|
||||
|
@ -437,9 +438,9 @@ class TestAssert_reprcompare(object):
|
|||
assert len(expl) > 1
|
||||
|
||||
def test_list_tuples(self):
|
||||
expl = callequal([], [(1,2)])
|
||||
expl = callequal([], [(1, 2)])
|
||||
assert len(expl) > 1
|
||||
expl = callequal([(1,2)], [])
|
||||
expl = callequal([(1, 2)], [])
|
||||
assert len(expl) > 1
|
||||
|
||||
def test_list_bad_repr(self):
|
||||
|
@ -609,7 +610,7 @@ class TestTruncateExplanation(object):
|
|||
|
||||
def test_doesnt_truncate_at_when_input_is_5_lines_and_LT_max_chars(self):
|
||||
expl = ['a' * 100 for x in range(5)]
|
||||
result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8*80)
|
||||
result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8 * 80)
|
||||
assert result == expl
|
||||
|
||||
def test_truncates_at_8_lines_when_given_list_of_empty_strings(self):
|
||||
|
@ -619,27 +620,27 @@ class TestTruncateExplanation(object):
|
|||
assert len(result) == 8 + self.LINES_IN_TRUNCATION_MSG
|
||||
assert "Full output truncated" in result[-1]
|
||||
assert "43 lines hidden" in result[-1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG -1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
|
||||
assert last_line_before_trunc_msg.endswith("...")
|
||||
|
||||
def test_truncates_at_8_lines_when_first_8_lines_are_LT_max_chars(self):
|
||||
expl = ['a' for x in range(100)]
|
||||
result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8*80)
|
||||
result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8 * 80)
|
||||
assert result != expl
|
||||
assert len(result) == 8 + self.LINES_IN_TRUNCATION_MSG
|
||||
assert "Full output truncated" in result[-1]
|
||||
assert "93 lines hidden" in result[-1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG -1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
|
||||
assert last_line_before_trunc_msg.endswith("...")
|
||||
|
||||
def test_truncates_at_8_lines_when_first_8_lines_are_EQ_max_chars(self):
|
||||
expl = ['a' * 80 for x in range(16)]
|
||||
result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8*80)
|
||||
result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8 * 80)
|
||||
assert result != expl
|
||||
assert len(result) == 8 + self.LINES_IN_TRUNCATION_MSG
|
||||
assert "Full output truncated" in result[-1]
|
||||
assert "9 lines hidden" in result[-1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG -1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
|
||||
assert last_line_before_trunc_msg.endswith("...")
|
||||
|
||||
def test_truncates_at_4_lines_when_first_4_lines_are_GT_max_chars(self):
|
||||
|
@ -649,7 +650,7 @@ class TestTruncateExplanation(object):
|
|||
assert len(result) == 4 + self.LINES_IN_TRUNCATION_MSG
|
||||
assert "Full output truncated" in result[-1]
|
||||
assert "7 lines hidden" in result[-1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG -1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
|
||||
assert last_line_before_trunc_msg.endswith("...")
|
||||
|
||||
def test_truncates_at_1_line_when_first_line_is_GT_max_chars(self):
|
||||
|
@ -659,7 +660,7 @@ class TestTruncateExplanation(object):
|
|||
assert len(result) == 1 + self.LINES_IN_TRUNCATION_MSG
|
||||
assert "Full output truncated" in result[-1]
|
||||
assert "1000 lines hidden" in result[-1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG -1]
|
||||
last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
|
||||
assert last_line_before_trunc_msg.endswith("...")
|
||||
|
||||
def test_full_output_truncated(self, monkeypatch, testdir):
|
||||
|
@ -712,6 +713,7 @@ def test_python25_compile_issue257(testdir):
|
|||
*1 failed*
|
||||
""")
|
||||
|
||||
|
||||
def test_rewritten(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_rewritten():
|
||||
|
@ -719,11 +721,13 @@ def test_rewritten(testdir):
|
|||
""")
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
|
||||
def test_reprcompare_notin(mock_config):
|
||||
detail = plugin.pytest_assertrepr_compare(
|
||||
mock_config, 'not in', 'foo', 'aaafoobbb')[1:]
|
||||
assert detail == ["'foo' is contained here:", ' aaafoobbb', '? +++']
|
||||
|
||||
|
||||
def test_pytest_assertrepr_compare_integration(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
|
@ -740,6 +744,7 @@ def test_pytest_assertrepr_compare_integration(testdir):
|
|||
"*E*50*",
|
||||
])
|
||||
|
||||
|
||||
def test_sequence_comparison_uses_repr(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
|
@ -772,12 +777,12 @@ def test_assertrepr_loaded_per_dir(testdir):
|
|||
b_conftest.write('def pytest_assertrepr_compare(): return ["summary b"]')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*def test_base():*',
|
||||
'*E*assert 1 == 2*',
|
||||
'*def test_a():*',
|
||||
'*E*assert summary a*',
|
||||
'*def test_b():*',
|
||||
'*E*assert summary b*'])
|
||||
'*def test_base():*',
|
||||
'*E*assert 1 == 2*',
|
||||
'*def test_a():*',
|
||||
'*E*assert summary a*',
|
||||
'*def test_b():*',
|
||||
'*E*assert summary b*'])
|
||||
|
||||
|
||||
def test_assertion_options(testdir):
|
||||
|
@ -791,6 +796,7 @@ def test_assertion_options(testdir):
|
|||
result = testdir.runpytest_subprocess("--assert=plain")
|
||||
assert "3 == 4" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_triple_quoted_string_issue113(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
|
@ -802,6 +808,7 @@ def test_triple_quoted_string_issue113(testdir):
|
|||
])
|
||||
assert 'SyntaxError' not in result.stdout.str()
|
||||
|
||||
|
||||
def test_traceback_failure(testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
def g():
|
||||
|
@ -822,7 +829,7 @@ def test_traceback_failure(testdir):
|
|||
"",
|
||||
"*test_*.py:6: ",
|
||||
"_ _ _ *",
|
||||
#"",
|
||||
# "",
|
||||
" def f(x):",
|
||||
"> assert x == g()",
|
||||
"E assert 3 == 2",
|
||||
|
@ -831,7 +838,7 @@ def test_traceback_failure(testdir):
|
|||
"*test_traceback_failure.py:4: AssertionError"
|
||||
])
|
||||
|
||||
result = testdir.runpytest(p1) # "auto"
|
||||
result = testdir.runpytest(p1) # "auto"
|
||||
result.stdout.fnmatch_lines([
|
||||
"*test_traceback_failure.py F",
|
||||
"====* FAILURES *====",
|
||||
|
@ -881,7 +888,7 @@ def test_exception_handling_no_traceback(testdir):
|
|||
])
|
||||
|
||||
|
||||
@pytest.mark.skipif("'__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')" )
|
||||
@pytest.mark.skipif("'__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')")
|
||||
def test_warn_missing(testdir):
|
||||
testdir.makepyfile("")
|
||||
result = testdir.run(sys.executable, "-OO", "-m", "pytest", "-h")
|
||||
|
@ -893,6 +900,7 @@ def test_warn_missing(testdir):
|
|||
"*WARNING*assert statements are not executed*",
|
||||
])
|
||||
|
||||
|
||||
def test_recursion_source_decode(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_something():
|
||||
|
@ -907,6 +915,7 @@ def test_recursion_source_decode(testdir):
|
|||
<Module*>
|
||||
""")
|
||||
|
||||
|
||||
def test_AssertionError_message(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
|
@ -920,6 +929,7 @@ def test_AssertionError_message(testdir):
|
|||
*AssertionError: (1, 2)*
|
||||
""")
|
||||
|
||||
|
||||
@pytest.mark.skipif(PY3, reason='This bug does not exist on PY3')
|
||||
def test_set_with_unsortable_elements():
|
||||
# issue #718
|
||||
|
@ -956,6 +966,7 @@ def test_set_with_unsortable_elements():
|
|||
""").strip()
|
||||
assert '\n'.join(expl) == dedent
|
||||
|
||||
|
||||
def test_diff_newline_at_end(monkeypatch, testdir):
|
||||
testdir.makepyfile(r"""
|
||||
def test_diff():
|
||||
|
@ -970,6 +981,7 @@ def test_diff_newline_at_end(monkeypatch, testdir):
|
|||
* ? +
|
||||
""")
|
||||
|
||||
|
||||
def test_assert_tuple_warning(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_tuple():
|
||||
|
@ -981,6 +993,7 @@ def test_assert_tuple_warning(testdir):
|
|||
'*assertion is always true*',
|
||||
])
|
||||
|
||||
|
||||
def test_assert_indirect_tuple_no_warning(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_tuple():
|
||||
|
@ -991,6 +1004,7 @@ def test_assert_indirect_tuple_no_warning(testdir):
|
|||
output = '\n'.join(result.stdout.lines)
|
||||
assert 'WR1' not in output
|
||||
|
||||
|
||||
def test_assert_with_unicode(monkeypatch, testdir):
|
||||
testdir.makepyfile(u"""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
@ -1000,6 +1014,7 @@ def test_assert_with_unicode(monkeypatch, testdir):
|
|||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['*AssertionError*'])
|
||||
|
||||
|
||||
def test_raise_unprintable_assertion_error(testdir):
|
||||
testdir.makepyfile(r"""
|
||||
def test_raise_assertion_error():
|
||||
|
@ -1008,6 +1023,7 @@ def test_raise_unprintable_assertion_error(testdir):
|
|||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([r"> raise AssertionError('\xff')", 'E AssertionError: *'])
|
||||
|
||||
|
||||
def test_raise_assertion_error_raisin_repr(testdir):
|
||||
testdir.makepyfile(u"""
|
||||
class RaisingRepr(object):
|
||||
|
@ -1019,6 +1035,7 @@ def test_raise_assertion_error_raisin_repr(testdir):
|
|||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['E AssertionError: <unprintable AssertionError object>'])
|
||||
|
||||
|
||||
def test_issue_1944(testdir):
|
||||
testdir.makepyfile("""
|
||||
def f():
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import glob
|
||||
import os
|
||||
import py_compile
|
||||
import stat
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
import py
|
||||
import pytest
|
||||
|
||||
ast = pytest.importorskip("ast")
|
||||
if sys.platform.startswith("java"):
|
||||
# XXX should be xfail
|
||||
pytest.skip("assert rewrite does currently not work on jython")
|
||||
|
||||
import _pytest._code
|
||||
from _pytest.assertion import util
|
||||
from _pytest.assertion.rewrite import rewrite_asserts, PYTEST_TAG, AssertionRewritingHook
|
||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||
|
||||
ast = pytest.importorskip("ast")
|
||||
if sys.platform.startswith("java"):
|
||||
# XXX should be xfail
|
||||
pytest.skip("assert rewrite does currently not work on jython")
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
mod._old_reprcompare = util._reprcompare
|
||||
_pytest._code._reprcompare = None
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
util._reprcompare = mod._old_reprcompare
|
||||
del mod._old_reprcompare
|
||||
|
@ -34,6 +35,7 @@ def rewrite(src):
|
|||
rewrite_asserts(tree)
|
||||
return tree
|
||||
|
||||
|
||||
def getmsg(f, extra_ns=None, must_pass=False):
|
||||
"""Rewrite the assertions in f, run it, and get the failure message."""
|
||||
src = '\n'.join(_pytest._code.Code(f).source().lines)
|
||||
|
@ -118,12 +120,12 @@ class TestAssertionRewrite(object):
|
|||
def f():
|
||||
assert a_global # noqa
|
||||
|
||||
assert getmsg(f, {"a_global" : False}) == "assert False"
|
||||
assert getmsg(f, {"a_global": False}) == "assert False"
|
||||
|
||||
def f():
|
||||
assert sys == 42
|
||||
|
||||
assert getmsg(f, {"sys" : sys}) == "assert sys == 42"
|
||||
assert getmsg(f, {"sys": sys}) == "assert sys == 42"
|
||||
|
||||
def f():
|
||||
assert cls == 42 # noqa
|
||||
|
@ -131,7 +133,7 @@ class TestAssertionRewrite(object):
|
|||
class X(object):
|
||||
pass
|
||||
|
||||
assert getmsg(f, {"cls" : X}) == "assert cls == 42"
|
||||
assert getmsg(f, {"cls": X}) == "assert cls == 42"
|
||||
|
||||
def test_assert_already_has_message(self):
|
||||
def f():
|
||||
|
@ -238,13 +240,13 @@ class TestAssertionRewrite(object):
|
|||
def f():
|
||||
assert x() and x()
|
||||
|
||||
assert getmsg(f, {"x" : x}) == """assert (False)
|
||||
assert getmsg(f, {"x": x}) == """assert (False)
|
||||
+ where False = x()"""
|
||||
|
||||
def f():
|
||||
assert False or x()
|
||||
|
||||
assert getmsg(f, {"x" : x}) == """assert (False or False)
|
||||
assert getmsg(f, {"x": x}) == """assert (False or False)
|
||||
+ where False = x()"""
|
||||
|
||||
def f():
|
||||
|
@ -255,7 +257,7 @@ class TestAssertionRewrite(object):
|
|||
def f():
|
||||
x = 1
|
||||
y = 2
|
||||
assert x in {1 : None} and y in {}
|
||||
assert x in {1: None} and y in {}
|
||||
|
||||
assert getmsg(f) == "assert (1 in {1: None} and 2 in {})"
|
||||
|
||||
|
@ -348,7 +350,7 @@ class TestAssertionRewrite(object):
|
|||
def g(a=42, *args, **kwargs):
|
||||
return False
|
||||
|
||||
ns = {"g" : g}
|
||||
ns = {"g": g}
|
||||
|
||||
def f():
|
||||
assert g()
|
||||
|
@ -389,7 +391,7 @@ class TestAssertionRewrite(object):
|
|||
|
||||
def f():
|
||||
x = "a"
|
||||
assert g(**{x : 2})
|
||||
assert g(**{x: 2})
|
||||
|
||||
assert getmsg(f, ns) == """assert False
|
||||
+ where False = g(**{'a': 2})"""
|
||||
|
@ -398,10 +400,10 @@ class TestAssertionRewrite(object):
|
|||
class X(object):
|
||||
g = 3
|
||||
|
||||
ns = {"x" : X}
|
||||
ns = {"x": X}
|
||||
|
||||
def f():
|
||||
assert not x.g # noqa
|
||||
assert not x.g # noqa
|
||||
|
||||
assert getmsg(f, ns) == """assert not 3
|
||||
+ where 3 = x.g"""
|
||||
|
@ -556,7 +558,7 @@ class TestRewriteOnImport(object):
|
|||
def test_readonly(self, testdir):
|
||||
sub = testdir.mkdir("testing")
|
||||
sub.join("test_readonly.py").write(
|
||||
py.builtin._totext("""
|
||||
py.builtin._totext("""
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()
|
||||
""").encode("utf-8"), "wb")
|
||||
|
@ -609,7 +611,7 @@ def test_rewritten():
|
|||
def test_optimized():
|
||||
"hello"
|
||||
assert test_optimized.__doc__ is None"""
|
||||
)
|
||||
)
|
||||
p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None,
|
||||
rootdir=testdir.tmpdir)
|
||||
tmp = "--basetemp=%s" % p
|
||||
|
@ -638,8 +640,8 @@ def test_rewritten():
|
|||
testdir.tmpdir.join("test_newlines.py").write(b, "wb")
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3,3),
|
||||
reason='packages without __init__.py not supported on python 2')
|
||||
@pytest.mark.skipif(sys.version_info < (3, 3),
|
||||
reason='packages without __init__.py not supported on python 2')
|
||||
def test_package_without__init__py(self, testdir):
|
||||
pkg = testdir.mkdir('a_package_without_init_py')
|
||||
pkg.join('module.py').ensure()
|
||||
|
|
|
@ -8,6 +8,7 @@ import shutil
|
|||
|
||||
pytest_plugins = "pytester",
|
||||
|
||||
|
||||
class TestNewAPI(object):
|
||||
def test_config_cache_makedir(self, testdir):
|
||||
testdir.makeini("[pytest]")
|
||||
|
@ -88,7 +89,6 @@ class TestNewAPI(object):
|
|||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
|
||||
def test_cache_reportheader(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_hello():
|
||||
|
@ -338,7 +338,6 @@ class TestLastFailed(object):
|
|||
lastfailed = rlf(fail_import=0, fail_run=1)
|
||||
assert list(lastfailed) == ['test_maybe.py::test_hello']
|
||||
|
||||
|
||||
def test_lastfailed_failure_subset(self, testdir, monkeypatch):
|
||||
|
||||
testdir.makepyfile(test_maybe="""
|
||||
|
@ -380,12 +379,10 @@ class TestLastFailed(object):
|
|||
result, lastfailed = rlf(fail_import=1, fail_run=0)
|
||||
assert sorted(list(lastfailed)) == ['test_maybe.py', 'test_maybe2.py']
|
||||
|
||||
|
||||
result, lastfailed = rlf(fail_import=0, fail_run=0,
|
||||
args=('test_maybe2.py',))
|
||||
assert list(lastfailed) == ['test_maybe.py']
|
||||
|
||||
|
||||
# edge case of test selection - even if we remember failures
|
||||
# from other tests we still need to run all tests if no test
|
||||
# matches the failures
|
||||
|
|
|
@ -49,10 +49,10 @@ def oswritebytes(fd, obj):
|
|||
os.write(fd, tobytes(obj))
|
||||
|
||||
|
||||
|
||||
def StdCaptureFD(out=True, err=True, in_=True):
|
||||
return capture.MultiCapture(out, err, in_, Capture=capture.FDCapture)
|
||||
|
||||
|
||||
def StdCapture(out=True, err=True, in_=True):
|
||||
return capture.MultiCapture(out, err, in_, Capture=capture.SysCapture)
|
||||
|
||||
|
@ -72,7 +72,7 @@ class TestCaptureManager(object):
|
|||
|
||||
@needsosdup
|
||||
@pytest.mark.parametrize("method",
|
||||
['no', 'sys', pytest.mark.skipif('not hasattr(os, "dup")', 'fd')])
|
||||
['no', 'sys', pytest.mark.skipif('not hasattr(os, "dup")', 'fd')])
|
||||
def test_capturing_basic_api(self, method):
|
||||
capouter = StdCaptureFD()
|
||||
old = sys.stdout, sys.stderr, sys.stdin
|
||||
|
@ -112,7 +112,7 @@ class TestCaptureManager(object):
|
|||
|
||||
@pytest.mark.parametrize("method", ['fd', 'sys'])
|
||||
def test_capturing_unicode(testdir, method):
|
||||
if hasattr(sys, "pypy_version_info") and sys.pypy_version_info < (2,2):
|
||||
if hasattr(sys, "pypy_version_info") and sys.pypy_version_info < (2, 2):
|
||||
pytest.xfail("does not work on pypy < 2.2")
|
||||
if sys.version_info >= (3, 0):
|
||||
obj = "'b\u00f6y'"
|
||||
|
@ -234,7 +234,7 @@ class TestPerTestCapturing(object):
|
|||
"setup func1*",
|
||||
"in func1*",
|
||||
"teardown func1*",
|
||||
#"*1 fixture failure*"
|
||||
# "*1 fixture failure*"
|
||||
])
|
||||
|
||||
def test_teardown_capturing_final(self, testdir):
|
||||
|
@ -705,6 +705,7 @@ def tmpfile(testdir):
|
|||
if not f.closed:
|
||||
f.close()
|
||||
|
||||
|
||||
@needsosdup
|
||||
def test_dupfile(tmpfile):
|
||||
flist = []
|
||||
|
@ -723,12 +724,14 @@ def test_dupfile(tmpfile):
|
|||
assert "01234" in repr(s)
|
||||
tmpfile.close()
|
||||
|
||||
|
||||
def test_dupfile_on_bytesio():
|
||||
io = py.io.BytesIO()
|
||||
f = capture.safe_text_dupfile(io, "wb")
|
||||
f.write("hello")
|
||||
assert io.getvalue() == b"hello"
|
||||
|
||||
|
||||
def test_dupfile_on_textio():
|
||||
io = py.io.TextIO()
|
||||
f = capture.safe_text_dupfile(io, "wb")
|
||||
|
@ -1052,6 +1055,7 @@ def test_fdcapture_tmpfile_remains_the_same(tmpfile, use):
|
|||
capfile2 = cap.err.tmpfile
|
||||
assert capfile2 == capfile
|
||||
|
||||
|
||||
@needsosdup
|
||||
def test_close_and_capture_again(testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -1071,7 +1075,6 @@ def test_close_and_capture_again(testdir):
|
|||
""")
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize('method', ['SysCapture', 'FDCapture'])
|
||||
def test_capturing_and_logging_fundamentals(testdir, method):
|
||||
if method == "StdCaptureFD" and not hasattr(os, 'dup'):
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
import pytest, py
|
||||
import pytest
|
||||
import py
|
||||
|
||||
from _pytest.main import Session, EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
class TestCollector(object):
|
||||
def test_collect_versus_item(self):
|
||||
from pytest import Collector, Item
|
||||
|
@ -42,11 +44,11 @@ class TestCollector(object):
|
|||
assert not (fn1 == fn3)
|
||||
assert fn1 != fn3
|
||||
|
||||
for fn in fn1,fn2,fn3:
|
||||
for fn in fn1, fn2, fn3:
|
||||
assert fn != 3
|
||||
assert fn != modcol
|
||||
assert fn != [1,2,3]
|
||||
assert [1,2,3] != fn
|
||||
assert fn != [1, 2, 3]
|
||||
assert [1, 2, 3] != fn
|
||||
assert modcol != fn
|
||||
|
||||
def test_getparent(self, testdir):
|
||||
|
@ -68,7 +70,6 @@ class TestCollector(object):
|
|||
parent = fn.getparent(pytest.Class)
|
||||
assert parent is cls
|
||||
|
||||
|
||||
def test_getcustomfile_roundtrip(self, testdir):
|
||||
hello = testdir.makefile(".xxx", hello="world")
|
||||
testdir.makepyfile(conftest="""
|
||||
|
@ -102,6 +103,7 @@ class TestCollector(object):
|
|||
'*no tests ran in*',
|
||||
])
|
||||
|
||||
|
||||
class TestCollectFS(object):
|
||||
def test_ignored_certain_directories(self, testdir):
|
||||
tmpdir = testdir.tmpdir
|
||||
|
@ -334,6 +336,7 @@ class TestCustomConftests(object):
|
|||
"*test_x*"
|
||||
])
|
||||
|
||||
|
||||
class TestSession(object):
|
||||
def test_parsearg(self, testdir):
|
||||
p = testdir.makepyfile("def test_func(): pass")
|
||||
|
@ -347,11 +350,11 @@ class TestSession(object):
|
|||
assert rcol.fspath == subdir
|
||||
parts = rcol._parsearg(p.basename)
|
||||
|
||||
assert parts[0] == target
|
||||
assert parts[0] == target
|
||||
assert len(parts) == 1
|
||||
parts = rcol._parsearg(p.basename + "::test_func")
|
||||
assert parts[0] == target
|
||||
assert parts[1] == "test_func"
|
||||
assert parts[0] == target
|
||||
assert parts[1] == "test_func"
|
||||
assert len(parts) == 2
|
||||
|
||||
def test_collect_topdir(self, testdir):
|
||||
|
@ -362,9 +365,9 @@ class TestSession(object):
|
|||
topdir = testdir.tmpdir
|
||||
rcol = Session(config)
|
||||
assert topdir == rcol.fspath
|
||||
#rootid = rcol.nodeid
|
||||
#root2 = rcol.perform_collect([rcol.nodeid], genitems=False)[0]
|
||||
#assert root2 == rcol, rootid
|
||||
# rootid = rcol.nodeid
|
||||
# root2 = rcol.perform_collect([rcol.nodeid], genitems=False)[0]
|
||||
# assert root2 == rcol, rootid
|
||||
colitems = rcol.perform_collect([rcol.nodeid], genitems=False)
|
||||
assert len(colitems) == 1
|
||||
assert colitems[0].fspath == p
|
||||
|
@ -460,7 +463,7 @@ class TestSession(object):
|
|||
("pytest_collectstart", "collector.fspath == test_aaa"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport",
|
||||
"report.nodeid.startswith('aaa/test_aaa.py')"),
|
||||
"report.nodeid.startswith('aaa/test_aaa.py')"),
|
||||
])
|
||||
|
||||
def test_collect_two_commandline_args(self, testdir):
|
||||
|
@ -510,6 +513,7 @@ class TestSession(object):
|
|||
# ensure we are reporting the collection of the single test item (#2464)
|
||||
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
|
||||
|
||||
|
||||
class Test_getinitialnodes(object):
|
||||
def test_global_file(self, testdir, tmpdir):
|
||||
x = tmpdir.ensure("x.py")
|
||||
|
@ -537,6 +541,7 @@ class Test_getinitialnodes(object):
|
|||
for col in col.listchain():
|
||||
assert col.config is config
|
||||
|
||||
|
||||
class Test_genitems(object):
|
||||
def test_check_collect_hashes(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
|
@ -689,6 +694,7 @@ COLLECTION_ERROR_PY_FILES = dict(
|
|||
""",
|
||||
)
|
||||
|
||||
|
||||
def test_exit_on_collection_error(testdir):
|
||||
"""Verify that all collection errors are collected and no tests executed"""
|
||||
testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
import py, pytest
|
||||
import py
|
||||
import pytest
|
||||
|
||||
import _pytest._code
|
||||
from _pytest.config import getcfg, get_common_ancestor, determine_setup
|
||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
class TestParseIni(object):
|
||||
|
||||
@pytest.mark.parametrize('section, filename',
|
||||
|
@ -85,6 +87,7 @@ class TestParseIni(object):
|
|||
result = testdir.inline_run("--confcutdir=.")
|
||||
assert result.ret == 0
|
||||
|
||||
|
||||
class TestConfigCmdlineParsing(object):
|
||||
def test_parsing_again_fails(self, testdir):
|
||||
config = testdir.parseconfig()
|
||||
|
@ -99,7 +102,7 @@ class TestConfigCmdlineParsing(object):
|
|||
[pytest]
|
||||
custom = 0
|
||||
""")
|
||||
testdir.makefile(".cfg", custom = """
|
||||
testdir.makefile(".cfg", custom="""
|
||||
[pytest]
|
||||
custom = 1
|
||||
""")
|
||||
|
@ -116,6 +119,7 @@ class TestConfigCmdlineParsing(object):
|
|||
ret = pytest.main("-c " + temp_cfg_file)
|
||||
assert ret == _pytest.main.EXIT_OK
|
||||
|
||||
|
||||
class TestConfigAPI(object):
|
||||
def test_config_trace(self, testdir):
|
||||
config = testdir.parseconfig()
|
||||
|
@ -149,7 +153,7 @@ class TestConfigAPI(object):
|
|||
def test_config_getvalueorskip(self, testdir):
|
||||
config = testdir.parseconfig()
|
||||
pytest.raises(pytest.skip.Exception,
|
||||
"config.getvalueorskip('hello')")
|
||||
"config.getvalueorskip('hello')")
|
||||
verbose = config.getvalueorskip("verbose")
|
||||
assert verbose == config.option.verbose
|
||||
|
||||
|
@ -472,6 +476,7 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch):
|
|||
plugin = config.pluginmanager.getplugin("mytestplugin")
|
||||
assert plugin is None
|
||||
|
||||
|
||||
def test_cmdline_processargs_simple(testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_cmdline_preparse(args):
|
||||
|
@ -483,6 +488,7 @@ def test_cmdline_processargs_simple(testdir):
|
|||
"*-h*",
|
||||
])
|
||||
|
||||
|
||||
def test_invalid_options_show_extra_information(testdir):
|
||||
"""display extra information when pytest exits due to unrecognized
|
||||
options in the command-line"""
|
||||
|
@ -528,6 +534,7 @@ def test_toolongargs_issue224(testdir):
|
|||
result = testdir.runpytest("-m", "hello" * 500)
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_config_in_subdirectory_colon_command_line_issue2148(testdir):
|
||||
conftest_source = '''
|
||||
def pytest_addoption(parser):
|
||||
|
@ -569,7 +576,7 @@ def test_notify_exception(testdir, capfd):
|
|||
|
||||
|
||||
def test_load_initial_conftest_last_ordering(testdir):
|
||||
from _pytest.config import get_config
|
||||
from _pytest.config import get_config
|
||||
pm = get_config().pluginmanager
|
||||
|
||||
class My(object):
|
||||
|
@ -643,6 +650,7 @@ class TestWarning(object):
|
|||
*hello*
|
||||
""")
|
||||
|
||||
|
||||
class TestRootdir(object):
|
||||
def test_simple_noini(self, tmpdir):
|
||||
assert get_common_ancestor([tmpdir]) == tmpdir
|
||||
|
@ -666,7 +674,7 @@ class TestRootdir(object):
|
|||
rootdir, inifile, inicfg = determine_setup(None, args)
|
||||
assert rootdir == tmpdir
|
||||
assert inifile == inifile
|
||||
rootdir, inifile, inicfg = determine_setup(None, [b,a])
|
||||
rootdir, inifile, inicfg = determine_setup(None, [b, a])
|
||||
assert rootdir == tmpdir
|
||||
assert inifile == inifile
|
||||
|
||||
|
@ -724,7 +732,6 @@ class TestOverrideIniArgs(object):
|
|||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["custom_option:3.0"])
|
||||
|
||||
|
||||
def test_override_ini_pathlist(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_addoption(parser):
|
||||
|
@ -826,4 +833,3 @@ class TestOverrideIniArgs(object):
|
|||
rootdir, inifile, inicfg = determine_setup(None, ['a/exist'])
|
||||
assert rootdir == tmpdir
|
||||
assert inifile is None
|
||||
|
||||
|
|
|
@ -19,11 +19,13 @@ def basedir(request, tmpdir_factory):
|
|||
tmpdir.ensure("adir/b/__init__.py")
|
||||
return tmpdir
|
||||
|
||||
|
||||
def ConftestWithSetinitial(path):
|
||||
conftest = PytestPluginManager()
|
||||
conftest_setinitial(conftest, [path])
|
||||
return conftest
|
||||
|
||||
|
||||
def conftest_setinitial(conftest, args, confcutdir=None):
|
||||
class Namespace(object):
|
||||
def __init__(self):
|
||||
|
@ -32,6 +34,7 @@ def conftest_setinitial(conftest, args, confcutdir=None):
|
|||
self.noconftest = False
|
||||
conftest._set_initial_conftests(Namespace())
|
||||
|
||||
|
||||
class TestConftestValueAccessGlobal(object):
|
||||
def test_basic_init(self, basedir):
|
||||
conftest = PytestPluginManager()
|
||||
|
@ -43,7 +46,7 @@ class TestConftestValueAccessGlobal(object):
|
|||
len(conftest._path2confmods)
|
||||
conftest._getconftestmodules(basedir)
|
||||
snap1 = len(conftest._path2confmods)
|
||||
#assert len(conftest._path2confmods) == snap1 + 1
|
||||
# assert len(conftest._path2confmods) == snap1 + 1
|
||||
conftest._getconftestmodules(basedir.join('adir'))
|
||||
assert len(conftest._path2confmods) == snap1 + 1
|
||||
conftest._getconftestmodules(basedir.join('b'))
|
||||
|
@ -65,11 +68,12 @@ class TestConftestValueAccessGlobal(object):
|
|||
startdir.ensure("xx", dir=True)
|
||||
conftest = ConftestWithSetinitial(startdir)
|
||||
mod, value = conftest._rget_with_confmod("a", startdir)
|
||||
assert value == 1.5
|
||||
assert value == 1.5
|
||||
path = py.path.local(mod.__file__)
|
||||
assert path.dirpath() == basedir.join("adir", "b")
|
||||
assert path.purebasename.startswith("conftest")
|
||||
|
||||
|
||||
def test_conftest_in_nonpkg_with_init(tmpdir):
|
||||
tmpdir.ensure("adir-1.0/conftest.py").write("a=1 ; Directory = 3")
|
||||
tmpdir.ensure("adir-1.0/b/conftest.py").write("b=2 ; a = 1.5")
|
||||
|
@ -77,6 +81,7 @@ def test_conftest_in_nonpkg_with_init(tmpdir):
|
|||
tmpdir.ensure("adir-1.0/__init__.py")
|
||||
ConftestWithSetinitial(tmpdir.join("adir-1.0", "b"))
|
||||
|
||||
|
||||
def test_doubledash_considered(testdir):
|
||||
conf = testdir.mkdir("--option")
|
||||
conf.join("conftest.py").ensure()
|
||||
|
@ -85,6 +90,7 @@ def test_doubledash_considered(testdir):
|
|||
l = conftest._getconftestmodules(conf)
|
||||
assert len(l) == 1
|
||||
|
||||
|
||||
def test_issue151_load_all_conftests(testdir):
|
||||
names = "code proj src".split()
|
||||
for name in names:
|
||||
|
@ -96,6 +102,7 @@ def test_issue151_load_all_conftests(testdir):
|
|||
d = list(conftest._conftestpath2mod.values())
|
||||
assert len(d) == len(names)
|
||||
|
||||
|
||||
def test_conftest_global_import(testdir):
|
||||
testdir.makeconftest("x=3")
|
||||
p = testdir.makepyfile("""
|
||||
|
@ -117,6 +124,7 @@ def test_conftest_global_import(testdir):
|
|||
res = testdir.runpython(p)
|
||||
assert res.ret == 0
|
||||
|
||||
|
||||
def test_conftestcutdir(testdir):
|
||||
conf = testdir.makeconftest("")
|
||||
p = testdir.mkdir("x")
|
||||
|
@ -136,6 +144,7 @@ def test_conftestcutdir(testdir):
|
|||
assert len(l) == 1
|
||||
assert l[0].__file__.startswith(str(conf))
|
||||
|
||||
|
||||
def test_conftestcutdir_inplace_considered(testdir):
|
||||
conf = testdir.makeconftest("")
|
||||
conftest = PytestPluginManager()
|
||||
|
@ -144,6 +153,7 @@ def test_conftestcutdir_inplace_considered(testdir):
|
|||
assert len(l) == 1
|
||||
assert l[0].__file__.startswith(str(conf))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", 'test tests whatever .dotdir'.split())
|
||||
def test_setinitial_conftest_subdirs(testdir, name):
|
||||
sub = testdir.mkdir(name)
|
||||
|
@ -151,12 +161,13 @@ def test_setinitial_conftest_subdirs(testdir, name):
|
|||
conftest = PytestPluginManager()
|
||||
conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir)
|
||||
if name not in ('whatever', '.dotdir'):
|
||||
assert subconftest in conftest._conftestpath2mod
|
||||
assert subconftest in conftest._conftestpath2mod
|
||||
assert len(conftest._conftestpath2mod) == 1
|
||||
else:
|
||||
assert subconftest not in conftest._conftestpath2mod
|
||||
assert subconftest not in conftest._conftestpath2mod
|
||||
assert len(conftest._conftestpath2mod) == 0
|
||||
|
||||
|
||||
def test_conftest_confcutdir(testdir):
|
||||
testdir.makeconftest("assert 0")
|
||||
x = testdir.mkdir("x")
|
||||
|
@ -168,6 +179,7 @@ def test_conftest_confcutdir(testdir):
|
|||
result.stdout.fnmatch_lines(["*--xyz*"])
|
||||
assert 'warning: could not load initial' not in result.stdout.str()
|
||||
|
||||
|
||||
def test_no_conftest(testdir):
|
||||
testdir.makeconftest("assert 0")
|
||||
result = testdir.runpytest("--noconftest")
|
||||
|
@ -176,6 +188,7 @@ def test_no_conftest(testdir):
|
|||
result = testdir.runpytest()
|
||||
assert result.ret == EXIT_USAGEERROR
|
||||
|
||||
|
||||
def test_conftest_existing_resultlog(testdir):
|
||||
x = testdir.mkdir("tests")
|
||||
x.join("conftest.py").write(_pytest._code.Source("""
|
||||
|
@ -186,6 +199,7 @@ def test_conftest_existing_resultlog(testdir):
|
|||
result = testdir.runpytest("-h", "--resultlog", "result.log")
|
||||
result.stdout.fnmatch_lines(["*--xyz*"])
|
||||
|
||||
|
||||
def test_conftest_existing_junitxml(testdir):
|
||||
x = testdir.mkdir("tests")
|
||||
x.join("conftest.py").write(_pytest._code.Source("""
|
||||
|
@ -196,6 +210,7 @@ def test_conftest_existing_junitxml(testdir):
|
|||
result = testdir.runpytest("-h", "--junitxml", "junit.xml")
|
||||
result.stdout.fnmatch_lines(["*--xyz*"])
|
||||
|
||||
|
||||
def test_conftest_import_order(testdir, monkeypatch):
|
||||
ct1 = testdir.makeconftest("")
|
||||
sub = testdir.mkdir("sub")
|
||||
|
@ -319,38 +334,38 @@ class TestConftestVisibility(object):
|
|||
# N.B.: "swc" stands for "subdir with conftest.py"
|
||||
# "snc" stands for "subdir no [i.e. without] conftest.py"
|
||||
@pytest.mark.parametrize("chdir,testarg,expect_ntests_passed", [
|
||||
# Effective target: package/..
|
||||
("runner", "..", 3),
|
||||
("package", "..", 3),
|
||||
("swc", "../..", 3),
|
||||
("snc", "../..", 3),
|
||||
# Effective target: package/..
|
||||
("runner", "..", 3),
|
||||
("package", "..", 3),
|
||||
("swc", "../..", 3),
|
||||
("snc", "../..", 3),
|
||||
|
||||
# Effective target: package
|
||||
("runner", "../package", 3),
|
||||
("package", ".", 3),
|
||||
("swc", "..", 3),
|
||||
("snc", "..", 3),
|
||||
# Effective target: package
|
||||
("runner", "../package", 3),
|
||||
("package", ".", 3),
|
||||
("swc", "..", 3),
|
||||
("snc", "..", 3),
|
||||
|
||||
# Effective target: package/swc
|
||||
("runner", "../package/swc", 1),
|
||||
("package", "./swc", 1),
|
||||
("swc", ".", 1),
|
||||
("snc", "../swc", 1),
|
||||
# Effective target: package/swc
|
||||
("runner", "../package/swc", 1),
|
||||
("package", "./swc", 1),
|
||||
("swc", ".", 1),
|
||||
("snc", "../swc", 1),
|
||||
|
||||
# Effective target: package/snc
|
||||
("runner", "../package/snc", 1),
|
||||
("package", "./snc", 1),
|
||||
("swc", "../snc", 1),
|
||||
("snc", ".", 1),
|
||||
# Effective target: package/snc
|
||||
("runner", "../package/snc", 1),
|
||||
("package", "./snc", 1),
|
||||
("swc", "../snc", 1),
|
||||
("snc", ".", 1),
|
||||
])
|
||||
@pytest.mark.issue616
|
||||
def test_parsefactories_relative_node_ids(
|
||||
self, testdir, chdir,testarg, expect_ntests_passed):
|
||||
self, testdir, chdir, testarg, expect_ntests_passed):
|
||||
dirs = self._setup_tree(testdir)
|
||||
print("pytest run in cwd: %s" %(
|
||||
print("pytest run in cwd: %s" % (
|
||||
dirs[chdir].relto(testdir.tmpdir)))
|
||||
print("pytestarg : %s" %(testarg))
|
||||
print("expected pass : %s" %(expect_ntests_passed))
|
||||
print("pytestarg : %s" % (testarg))
|
||||
print("expected pass : %s" % (expect_ntests_passed))
|
||||
with dirs[chdir].as_cwd():
|
||||
reprec = testdir.inline_run(testarg, "-q", "--traceconfig")
|
||||
reprec.assertoutcome(passed=expect_ntests_passed)
|
||||
|
|
|
@ -19,7 +19,7 @@ class TestDoctests(object):
|
|||
""")
|
||||
|
||||
for x in (testdir.tmpdir, checkfile):
|
||||
#print "checking that %s returns custom items" % (x,)
|
||||
# print "checking that %s returns custom items" % (x,)
|
||||
items, reprec = testdir.inline_genitems(x)
|
||||
assert len(items) == 1
|
||||
assert isinstance(items[0], DoctestItem)
|
||||
|
@ -32,14 +32,14 @@ class TestDoctests(object):
|
|||
path = testdir.makepyfile(whatever="#")
|
||||
for p in (path, testdir.tmpdir):
|
||||
items, reprec = testdir.inline_genitems(p,
|
||||
'--doctest-modules')
|
||||
'--doctest-modules')
|
||||
assert len(items) == 0
|
||||
|
||||
def test_collect_module_single_modulelevel_doctest(self, testdir):
|
||||
path = testdir.makepyfile(whatever='""">>> pass"""')
|
||||
for p in (path, testdir.tmpdir):
|
||||
items, reprec = testdir.inline_genitems(p,
|
||||
'--doctest-modules')
|
||||
'--doctest-modules')
|
||||
assert len(items) == 1
|
||||
assert isinstance(items[0], DoctestItem)
|
||||
assert isinstance(items[0].parent, DoctestModule)
|
||||
|
@ -52,7 +52,7 @@ class TestDoctests(object):
|
|||
""")
|
||||
for p in (path, testdir.tmpdir):
|
||||
items, reprec = testdir.inline_genitems(p,
|
||||
'--doctest-modules')
|
||||
'--doctest-modules')
|
||||
assert len(items) == 2
|
||||
assert isinstance(items[0], DoctestItem)
|
||||
assert isinstance(items[1], DoctestItem)
|
||||
|
@ -77,7 +77,7 @@ class TestDoctests(object):
|
|||
""")
|
||||
for p in (path, testdir.tmpdir):
|
||||
items, reprec = testdir.inline_genitems(p,
|
||||
'--doctest-modules')
|
||||
'--doctest-modules')
|
||||
assert len(items) == 2
|
||||
assert isinstance(items[0], DoctestItem)
|
||||
assert isinstance(items[1], DoctestItem)
|
||||
|
@ -135,9 +135,9 @@ class TestDoctests(object):
|
|||
@pytest.mark.parametrize(
|
||||
' test_string, encoding',
|
||||
[
|
||||
(u'foo', 'ascii'),
|
||||
(u'öäü', 'latin1'),
|
||||
(u'öäü', 'utf-8')
|
||||
(u'foo', 'ascii'),
|
||||
(u'öäü', 'latin1'),
|
||||
(u'öäü', 'utf-8')
|
||||
]
|
||||
)
|
||||
def test_encoding(self, testdir, test_string, encoding):
|
||||
|
@ -294,7 +294,6 @@ class TestDoctests(object):
|
|||
"*:5: DocTestFailure"
|
||||
])
|
||||
|
||||
|
||||
def test_txtfile_failing(self, testdir):
|
||||
p = testdir.maketxtfile("""
|
||||
>>> i = 0
|
||||
|
@ -535,7 +534,7 @@ class TestDoctests(object):
|
|||
p = testdir.makepyfile(test_unicode_doctest_module="""
|
||||
# -*- encoding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
def fix_bad_unicode(text):
|
||||
'''
|
||||
>>> print(fix_bad_unicode('único'))
|
||||
|
@ -932,4 +931,3 @@ class TestDoctestReportingOption(object):
|
|||
result.stderr.fnmatch_lines([
|
||||
"*error: argument --doctest-report: invalid choice: 'obviously_invalid_format' (choose from*"
|
||||
])
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@ from __future__ import absolute_import, division, print_function
|
|||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||
import pytest
|
||||
|
||||
|
||||
def test_version(testdir, pytestconfig):
|
||||
result = testdir.runpytest("--version")
|
||||
assert result.ret == 0
|
||||
#p = py.path.local(py.__file__).dirpath()
|
||||
# p = py.path.local(py.__file__).dirpath()
|
||||
result.stderr.fnmatch_lines([
|
||||
'*pytest*%s*imported from*' % (pytest.__version__, )
|
||||
])
|
||||
|
@ -15,6 +16,7 @@ def test_version(testdir, pytestconfig):
|
|||
"*at*",
|
||||
])
|
||||
|
||||
|
||||
def test_help(testdir):
|
||||
result = testdir.runpytest("--help")
|
||||
assert result.ret == 0
|
||||
|
@ -26,6 +28,7 @@ def test_help(testdir):
|
|||
*to see*fixtures*pytest --fixtures*
|
||||
""")
|
||||
|
||||
|
||||
def test_hookvalidation_unknown(testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_hello(xyz):
|
||||
|
@ -37,6 +40,7 @@ def test_hookvalidation_unknown(testdir):
|
|||
'*unknown hook*pytest_hello*'
|
||||
])
|
||||
|
||||
|
||||
def test_hookvalidation_optional(testdir):
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
|
@ -47,6 +51,7 @@ def test_hookvalidation_optional(testdir):
|
|||
result = testdir.runpytest()
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_traceconfig(testdir):
|
||||
result = testdir.runpytest("--traceconfig")
|
||||
result.stdout.fnmatch_lines([
|
||||
|
@ -54,12 +59,14 @@ def test_traceconfig(testdir):
|
|||
"*active plugins*",
|
||||
])
|
||||
|
||||
|
||||
def test_debug(testdir, monkeypatch):
|
||||
result = testdir.runpytest_subprocess("--debug")
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
p = testdir.tmpdir.join("pytestdebug.log")
|
||||
assert "pytest_sessionstart" in p.read()
|
||||
|
||||
|
||||
def test_PYTEST_DEBUG(testdir, monkeypatch):
|
||||
monkeypatch.setenv("PYTEST_DEBUG", "1")
|
||||
result = testdir.runpytest_subprocess()
|
||||
|
|
|
@ -600,6 +600,7 @@ class TestPython(object):
|
|||
assert "hello-stdout call" in systemout.toxml()
|
||||
assert "hello-stdout teardown" in systemout.toxml()
|
||||
|
||||
|
||||
def test_mangle_test_address():
|
||||
from _pytest.junitxml import mangle_test_address
|
||||
address = '::'.join(
|
||||
|
@ -760,11 +761,13 @@ def test_logxml_makedir(testdir):
|
|||
assert result.ret == 0
|
||||
assert testdir.tmpdir.join("path/to/results.xml").check()
|
||||
|
||||
|
||||
def test_logxml_check_isdir(testdir):
|
||||
"""Give an error if --junit-xml is a directory (#2089)"""
|
||||
result = testdir.runpytest("--junit-xml=.")
|
||||
result.stderr.fnmatch_lines(["*--junitxml must be a filename*"])
|
||||
|
||||
|
||||
def test_escaped_parametrized_names_xml(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -1057,4 +1060,3 @@ def test_set_suite_name(testdir, suite_name):
|
|||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(name=expected)
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@ import sys
|
|||
import pytest
|
||||
from _pytest.mark import MarkGenerator as Mark, ParameterSet
|
||||
|
||||
|
||||
class TestMark(object):
|
||||
def test_markinfo_repr(self):
|
||||
from _pytest.mark import MarkInfo, Mark
|
||||
m = MarkInfo(Mark("hello", (1,2), {}))
|
||||
m = MarkInfo(Mark("hello", (1, 2), {}))
|
||||
repr(m)
|
||||
|
||||
@pytest.mark.parametrize('attr', ['mark', 'param'])
|
||||
|
@ -140,6 +141,7 @@ def test_ini_markers(testdir):
|
|||
rec = testdir.inline_run()
|
||||
rec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
def test_markers_option(testdir):
|
||||
testdir.makeini("""
|
||||
[pytest]
|
||||
|
@ -153,6 +155,7 @@ def test_markers_option(testdir):
|
|||
"*a1some*another marker",
|
||||
])
|
||||
|
||||
|
||||
def test_markers_option_with_plugin_in_current_dir(testdir):
|
||||
testdir.makeconftest('pytest_plugins = "flip_flop"')
|
||||
testdir.makepyfile(flip_flop="""\
|
||||
|
@ -186,6 +189,7 @@ def test_mark_on_pseudo_function(testdir):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
def test_strict_prohibits_unregistered_markers(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -199,11 +203,12 @@ def test_strict_prohibits_unregistered_markers(testdir):
|
|||
"*unregisteredmark*not*registered*",
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("spec", [
|
||||
("xyz", ("test_one",)),
|
||||
("xyz and xyz2", ()),
|
||||
("xyz2", ("test_two",)),
|
||||
("xyz or xyz2", ("test_one", "test_two"),)
|
||||
("xyz", ("test_one",)),
|
||||
("xyz and xyz2", ()),
|
||||
("xyz2", ("test_two",)),
|
||||
("xyz or xyz2", ("test_one", "test_two"),)
|
||||
])
|
||||
def test_mark_option(spec, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -222,9 +227,10 @@ def test_mark_option(spec, testdir):
|
|||
assert len(passed) == len(passed_result)
|
||||
assert list(passed) == list(passed_result)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("spec", [
|
||||
("interface", ("test_interface",)),
|
||||
("not interface", ("test_nointer",)),
|
||||
("interface", ("test_interface",)),
|
||||
("not interface", ("test_nointer",)),
|
||||
])
|
||||
def test_mark_option_custom(spec, testdir):
|
||||
testdir.makeconftest("""
|
||||
|
@ -247,11 +253,12 @@ def test_mark_option_custom(spec, testdir):
|
|||
assert len(passed) == len(passed_result)
|
||||
assert list(passed) == list(passed_result)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("spec", [
|
||||
("interface", ("test_interface",)),
|
||||
("not interface", ("test_nointer", "test_pass")),
|
||||
("pass", ("test_pass",)),
|
||||
("not pass", ("test_interface", "test_nointer")),
|
||||
("interface", ("test_interface",)),
|
||||
("not interface", ("test_nointer", "test_pass")),
|
||||
("pass", ("test_pass",)),
|
||||
("not pass", ("test_interface", "test_nointer")),
|
||||
])
|
||||
def test_keyword_option_custom(spec, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -271,9 +278,9 @@ def test_keyword_option_custom(spec, testdir):
|
|||
|
||||
|
||||
@pytest.mark.parametrize("spec", [
|
||||
("None", ("test_func[None]",)),
|
||||
("1.3", ("test_func[1.3]",)),
|
||||
("2-3", ("test_func[2-3]",))
|
||||
("None", ("test_func[None]",)),
|
||||
("1.3", ("test_func[1.3]",)),
|
||||
("2-3", ("test_func[2-3]",))
|
||||
])
|
||||
def test_keyword_option_parametrize(spec, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -455,7 +462,6 @@ class TestFunctional(object):
|
|||
items, rec = testdir.inline_genitems(p)
|
||||
self.assert_markers(items, test_foo=('a', 'b'), test_bar=('a',))
|
||||
|
||||
|
||||
@pytest.mark.issue568
|
||||
@pytest.mark.xfail(reason="markers smear on methods of base classes")
|
||||
def test_mark_should_not_pass_to_siebling_class(self, testdir):
|
||||
|
@ -480,7 +486,6 @@ class TestFunctional(object):
|
|||
assert not hasattr(base_item.obj, 'b')
|
||||
assert not hasattr(sub_item_other.obj, 'b')
|
||||
|
||||
|
||||
def test_mark_decorator_baseclasses_merged(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import pytest
|
||||
|
|
|
@ -319,10 +319,11 @@ def test_issue156_undo_staticmethod(Sample):
|
|||
monkeypatch.undo()
|
||||
assert Sample.hello()
|
||||
|
||||
|
||||
def test_issue1338_name_resolving():
|
||||
pytest.importorskip('requests')
|
||||
monkeypatch = MonkeyPatch()
|
||||
try:
|
||||
monkeypatch.delattr('requests.sessions.Session.request')
|
||||
monkeypatch.delattr('requests.sessions.Session.request')
|
||||
finally:
|
||||
monkeypatch.undo()
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
import pytest
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
mod.nose = pytest.importorskip("nose")
|
||||
|
||||
|
||||
def test_nose_setup(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
l = []
|
||||
|
@ -44,6 +46,7 @@ def test_setup_func_not_callable():
|
|||
|
||||
call_optional(A(), "f")
|
||||
|
||||
|
||||
def test_nose_setup_func(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
from nose.tools import with_setup
|
||||
|
@ -112,6 +115,7 @@ def test_nose_setup_func_failure_2(testdir):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
def test_nose_setup_partial(testdir):
|
||||
pytest.importorskip("functools")
|
||||
p = testdir.makepyfile("""
|
||||
|
@ -266,6 +270,7 @@ def test_nose_style_setup_teardown(testdir):
|
|||
"*2 passed*",
|
||||
])
|
||||
|
||||
|
||||
def test_nose_setup_ordering(testdir):
|
||||
testdir.makepyfile("""
|
||||
def setup_module(mod):
|
||||
|
@ -305,6 +310,7 @@ def test_apiwrapper_problem_issue260(testdir):
|
|||
result = testdir.runpytest()
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
|
||||
def test_setup_teardown_linking_issue265(testdir):
|
||||
# we accidentally didnt integrate nose setupstate with normal setupstate
|
||||
# this test ensures that won't happen again
|
||||
|
@ -352,6 +358,7 @@ def test_SkipTest_in_test(testdir):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
|
||||
def test_istest_function_decorator(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import nose.tools
|
||||
|
@ -362,6 +369,7 @@ def test_istest_function_decorator(testdir):
|
|||
result = testdir.runpytest(p)
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
|
||||
def test_nottest_function_decorator(testdir):
|
||||
testdir.makepyfile("""
|
||||
import nose.tools
|
||||
|
@ -374,6 +382,7 @@ def test_nottest_function_decorator(testdir):
|
|||
calls = reprec.getreports("pytest_runtest_logreport")
|
||||
assert not calls
|
||||
|
||||
|
||||
def test_istest_class_decorator(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import nose.tools
|
||||
|
@ -385,6 +394,7 @@ def test_istest_class_decorator(testdir):
|
|||
result = testdir.runpytest(p)
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
|
||||
def test_nottest_class_decorator(testdir):
|
||||
testdir.makepyfile("""
|
||||
import nose.tools
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
import sys
|
||||
import os
|
||||
import py, pytest
|
||||
import py
|
||||
import pytest
|
||||
from _pytest import config as parseopt
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def parser():
|
||||
return parseopt.Parser()
|
||||
|
||||
|
||||
class TestParser(object):
|
||||
def test_no_help_by_default(self, capsys):
|
||||
parser = parseopt.Parser(usage="xyz")
|
||||
|
@ -161,12 +164,12 @@ class TestParser(object):
|
|||
assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
|
||||
args = parser.parse(['-R', '-S', '4', '2', '-R'])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
|
||||
assert args.R == True
|
||||
assert args.S == False
|
||||
assert args.R is True
|
||||
assert args.S is False
|
||||
args = parser.parse(['-R', '4', '-S', '2'])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
|
||||
assert args.R == True
|
||||
assert args.S == False
|
||||
assert args.R is True
|
||||
assert args.S is False
|
||||
|
||||
def test_parse_defaultgetter(self):
|
||||
def defaultget(option):
|
||||
|
@ -188,7 +191,7 @@ class TestParser(object):
|
|||
def test_drop_short_helper(self):
|
||||
parser = py.std.argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
|
||||
parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
|
||||
help='foo').map_long_option = {'two': 'two-word'}
|
||||
help='foo').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'}
|
||||
|
@ -238,18 +241,18 @@ class TestParser(object):
|
|||
assert args.file_or_dir == ['abcd']
|
||||
|
||||
def test_drop_short_help0(self, parser, capsys):
|
||||
parser.addoption('--func-args', '--doit', help = 'foo',
|
||||
parser.addoption('--func-args', '--doit', help='foo',
|
||||
action='store_true')
|
||||
parser.parse([])
|
||||
help = parser.optparser.format_help()
|
||||
assert '--func-args, --doit foo' in help
|
||||
assert '--func-args, --doit foo' in help
|
||||
|
||||
# testing would be more helpful with all help generated
|
||||
def test_drop_short_help1(self, parser, capsys):
|
||||
group = parser.getgroup("general")
|
||||
group.addoption('--doit', '--func-args', action='store_true', help='foo')
|
||||
group._addoption("-h", "--help", action="store_true", dest="help",
|
||||
help="show help message and configuration info")
|
||||
help="show help message and configuration info")
|
||||
parser.parse(['-h'])
|
||||
help = parser.optparser.format_help()
|
||||
assert '-doit, --func-args foo' in help
|
||||
|
@ -273,7 +276,7 @@ def test_argcomplete(testdir, monkeypatch):
|
|||
script = str(testdir.tmpdir.join("test_argcomplete"))
|
||||
pytest_bin = sys.argv[0]
|
||||
if "pytest" not in os.path.basename(pytest_bin):
|
||||
pytest.skip("need to be run with pytest executable, not %s" %(pytest_bin,))
|
||||
pytest.skip("need to be run with pytest executable, not %s" % (pytest_bin,))
|
||||
|
||||
with open(str(script), 'w') as fp:
|
||||
# redirect output from argcomplete to stdin and stderr is not trivial
|
||||
|
@ -284,7 +287,7 @@ def test_argcomplete(testdir, monkeypatch):
|
|||
# to handle a keyword argument env that replaces os.environ in popen or
|
||||
# extends the copy, advantage: could not forget to restore
|
||||
monkeypatch.setenv('_ARGCOMPLETE', "1")
|
||||
monkeypatch.setenv('_ARGCOMPLETE_IFS',"\x0b")
|
||||
monkeypatch.setenv('_ARGCOMPLETE_IFS', "\x0b")
|
||||
monkeypatch.setenv('COMP_WORDBREAKS', ' \\t\\n"\\\'><=;|&(:')
|
||||
|
||||
arg = '--fu'
|
||||
|
@ -297,12 +300,12 @@ def test_argcomplete(testdir, monkeypatch):
|
|||
elif not result.stdout.str():
|
||||
pytest.skip("bash provided no output, argcomplete not available?")
|
||||
else:
|
||||
if py.std.sys.version_info < (2,7):
|
||||
if py.std.sys.version_info < (2, 7):
|
||||
result.stdout.lines = result.stdout.lines[0].split('\x0b')
|
||||
result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
|
||||
else:
|
||||
result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
|
||||
if py.std.sys.version_info < (2,7):
|
||||
if py.std.sys.version_info < (2, 7):
|
||||
return
|
||||
os.mkdir('test_argcomplete.d')
|
||||
arg = 'test_argc'
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import absolute_import, division, print_function
|
|||
import sys
|
||||
import pytest
|
||||
|
||||
|
||||
class TestPasteCapture(object):
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -26,7 +27,7 @@ class TestPasteCapture(object):
|
|||
assert len(pastebinlist) == 1
|
||||
s = pastebinlist[0]
|
||||
assert s.find("def test_fail") != -1
|
||||
assert reprec.countoutcomes() == [1,1,1]
|
||||
assert reprec.countoutcomes() == [1, 1, 1]
|
||||
|
||||
def test_all(self, testdir, pastebinlist):
|
||||
from _pytest.pytester import LineMatcher
|
||||
|
@ -40,7 +41,7 @@ class TestPasteCapture(object):
|
|||
pytest.skip("")
|
||||
""")
|
||||
reprec = testdir.inline_run(testpath, "--pastebin=all", '-v')
|
||||
assert reprec.countoutcomes() == [1,1,1]
|
||||
assert reprec.countoutcomes() == [1, 1, 1]
|
||||
assert len(pastebinlist) == 1
|
||||
contents = pastebinlist[0].decode('utf-8')
|
||||
matcher = LineMatcher(contents.splitlines())
|
||||
|
@ -114,5 +115,3 @@ class TestPaste(object):
|
|||
assert 'lexer=%s' % lexer in data.decode()
|
||||
assert 'code=full-paste-contents' in data.decode()
|
||||
assert 'expiry=1week' in data.decode()
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ def runpdb_and_get_report(testdir, source):
|
|||
p = testdir.makepyfile(source)
|
||||
result = testdir.runpytest_inprocess("--pdb", p)
|
||||
reports = result.reprec.getreports("pytest_runtest_logreport")
|
||||
assert len(reports) == 3, reports # setup/call/teardown
|
||||
assert len(reports) == 3, reports # setup/call/teardown
|
||||
return reports[1]
|
||||
|
||||
|
||||
|
@ -33,7 +33,6 @@ def custom_pdb_calls():
|
|||
return called
|
||||
|
||||
|
||||
|
||||
class TestPDB(object):
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -181,7 +180,7 @@ class TestPDB(object):
|
|||
xxx
|
||||
""")
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
#child.expect(".*import pytest.*")
|
||||
# child.expect(".*import pytest.*")
|
||||
child.expect("(Pdb)")
|
||||
child.sendeof()
|
||||
child.expect("1 error")
|
||||
|
@ -194,7 +193,7 @@ class TestPDB(object):
|
|||
""")
|
||||
p1 = testdir.makepyfile("def test_func(): pass")
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
#child.expect(".*import pytest.*")
|
||||
# child.expect(".*import pytest.*")
|
||||
child.expect("(Pdb)")
|
||||
child.sendeof()
|
||||
self.flush(child)
|
||||
|
@ -216,7 +215,7 @@ class TestPDB(object):
|
|||
rest = child.read().decode("utf-8")
|
||||
assert "1 failed" in rest
|
||||
assert "def test_1" in rest
|
||||
assert "hello17" in rest # out is captured
|
||||
assert "hello17" in rest # out is captured
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_set_trace_interception(self, testdir):
|
||||
|
@ -309,8 +308,8 @@ class TestPDB(object):
|
|||
rest = child.read().decode("utf8")
|
||||
assert "1 failed" in rest
|
||||
assert "def test_1" in rest
|
||||
assert "hello17" in rest # out is captured
|
||||
assert "hello18" in rest # out is captured
|
||||
assert "hello17" in rest # out is captured
|
||||
assert "hello18" in rest # out is captured
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_used_outside_test(self, testdir):
|
||||
|
@ -319,7 +318,7 @@ class TestPDB(object):
|
|||
pytest.set_trace()
|
||||
x = 5
|
||||
""")
|
||||
child = testdir.spawn("%s %s" %(sys.executable, p1))
|
||||
child = testdir.spawn("%s %s" % (sys.executable, p1))
|
||||
child.expect("x = 5")
|
||||
child.sendeof()
|
||||
self.flush(child)
|
||||
|
@ -377,7 +376,6 @@ class TestPDB(object):
|
|||
])
|
||||
assert custom_pdb_calls == ["init", "reset", "interaction"]
|
||||
|
||||
|
||||
def test_pdb_custom_cls_without_pdb(self, testdir, custom_pdb_calls):
|
||||
p1 = testdir.makepyfile("""xxx """)
|
||||
result = testdir.runpytest_inprocess(
|
||||
|
|
|
@ -12,6 +12,7 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED, Session
|
|||
def pytestpm():
|
||||
return PytestPluginManager()
|
||||
|
||||
|
||||
class TestPytestPluginInteractions(object):
|
||||
def test_addhooks_conftestplugin(self, testdir):
|
||||
testdir.makepyfile(newhooks="""
|
||||
|
@ -29,9 +30,9 @@ class TestPytestPluginInteractions(object):
|
|||
config = get_config()
|
||||
pm = config.pluginmanager
|
||||
pm.hook.pytest_addhooks.call_historic(
|
||||
kwargs=dict(pluginmanager=config.pluginmanager))
|
||||
kwargs=dict(pluginmanager=config.pluginmanager))
|
||||
config.pluginmanager._importconftest(conf)
|
||||
#print(config.pluginmanager.get_plugins())
|
||||
# print(config.pluginmanager.get_plugins())
|
||||
res = config.hook.pytest_myhook(xyz=10)
|
||||
assert res == [11]
|
||||
|
||||
|
@ -197,6 +198,7 @@ def test_namespace_has_default_and_env_plugins(testdir):
|
|||
result = testdir.runpython(p)
|
||||
assert result.ret == 0
|
||||
|
||||
|
||||
def test_default_markers(testdir):
|
||||
result = testdir.runpytest("--markers")
|
||||
result.stdout.fnmatch_lines([
|
||||
|
@ -232,7 +234,7 @@ class TestPytestPluginManager(object):
|
|||
assert mod in l
|
||||
pytest.raises(ValueError, "pm.register(mod)")
|
||||
pytest.raises(ValueError, lambda: pm.register(mod))
|
||||
#assert not pm.is_registered(mod2)
|
||||
# assert not pm.is_registered(mod2)
|
||||
assert pm.get_plugins() == l
|
||||
|
||||
def test_canonical_import(self, monkeypatch):
|
||||
|
@ -259,7 +261,7 @@ class TestPytestPluginManager(object):
|
|||
mod.pytest_plugins = "pytest_a"
|
||||
aplugin = testdir.makepyfile(pytest_a="#")
|
||||
reprec = testdir.make_hook_recorder(pytestpm)
|
||||
#syspath.prepend(aplugin.dirpath())
|
||||
# syspath.prepend(aplugin.dirpath())
|
||||
py.std.sys.path.insert(0, str(aplugin.dirpath()))
|
||||
pytestpm.consider_module(mod)
|
||||
call = reprec.getcall(pytestpm.hook.pytest_plugin_registered.name)
|
||||
|
@ -352,7 +354,7 @@ class TestPytestPluginManager(object):
|
|||
class TestPytestPluginManagerBootstrapming(object):
|
||||
def test_preparse_args(self, pytestpm):
|
||||
pytest.raises(ImportError, lambda:
|
||||
pytestpm.consider_preparse(["xyz", "-p", "hello123"]))
|
||||
pytestpm.consider_preparse(["xyz", "-p", "hello123"]))
|
||||
|
||||
def test_plugin_prevent_register(self, pytestpm):
|
||||
pytestpm.consider_preparse(["xyz", "-p", "no:abc"])
|
||||
|
|
|
@ -64,6 +64,7 @@ def test_parseconfig(testdir):
|
|||
assert config2 != config1
|
||||
assert config1 != pytest.config
|
||||
|
||||
|
||||
def test_testdir_runs_with_plugin(testdir):
|
||||
testdir.makepyfile("""
|
||||
pytest_plugins = "pytester"
|
||||
|
@ -78,6 +79,7 @@ def make_holder():
|
|||
class apiclass(object):
|
||||
def pytest_xyz(self, arg):
|
||||
"x"
|
||||
|
||||
def pytest_xyz_noarg(self):
|
||||
"x"
|
||||
|
||||
|
@ -117,6 +119,7 @@ def test_makepyfile_unicode(testdir):
|
|||
unichr = chr
|
||||
testdir.makepyfile(unichr(0xfffd))
|
||||
|
||||
|
||||
def test_inline_run_clean_modules(testdir):
|
||||
test_mod = testdir.makepyfile("def test_foo(): assert True")
|
||||
result = testdir.inline_run(str(test_mod))
|
||||
|
@ -126,6 +129,7 @@ def test_inline_run_clean_modules(testdir):
|
|||
result2 = testdir.inline_run(str(test_mod))
|
||||
assert result2.ret == EXIT_TESTSFAILED
|
||||
|
||||
|
||||
def test_assert_outcomes_after_pytest_erro(testdir):
|
||||
testdir.makepyfile("def test_foo(): assert True")
|
||||
|
||||
|
|
|
@ -283,9 +283,11 @@ class TestWarns(object):
|
|||
assert str(record[0].message) == "user"
|
||||
assert str(record[1].message) == "runtime"
|
||||
|
||||
class MyUserWarning(UserWarning): pass
|
||||
class MyUserWarning(UserWarning):
|
||||
pass
|
||||
|
||||
class MyRuntimeWarning(RuntimeWarning): pass
|
||||
class MyRuntimeWarning(RuntimeWarning):
|
||||
pass
|
||||
|
||||
with pytest.warns((UserWarning, RuntimeWarning)) as record:
|
||||
warnings.warn("user", MyUserWarning)
|
||||
|
@ -295,7 +297,6 @@ class TestWarns(object):
|
|||
assert str(record[0].message) == "user"
|
||||
assert str(record[1].message) == "runtime"
|
||||
|
||||
|
||||
def test_double_test(self, testdir):
|
||||
"""If a test is run again, the warning should still be raised"""
|
||||
testdir.makepyfile('''
|
||||
|
|
|
@ -6,7 +6,7 @@ import py
|
|||
import pytest
|
||||
from _pytest.main import Node, Item, FSCollector
|
||||
from _pytest.resultlog import generic_path, ResultLog, \
|
||||
pytest_configure, pytest_unconfigure
|
||||
pytest_configure, pytest_unconfigure
|
||||
|
||||
|
||||
def test_generic_path(testdir):
|
||||
|
@ -14,10 +14,10 @@ def test_generic_path(testdir):
|
|||
config = testdir.parseconfig()
|
||||
session = Session(config)
|
||||
p1 = Node('a', config=config, session=session)
|
||||
#assert p1.fspath is None
|
||||
# assert p1.fspath is None
|
||||
p2 = Node('B', parent=p1)
|
||||
p3 = Node('()', parent = p2)
|
||||
item = Item('c', parent = p3)
|
||||
p3 = Node('()', parent=p2)
|
||||
item = Item('c', parent=p3)
|
||||
|
||||
res = generic_path(item)
|
||||
assert res == 'a.B().c'
|
||||
|
@ -25,13 +25,14 @@ def test_generic_path(testdir):
|
|||
p0 = FSCollector('proj/test', config=config, session=session)
|
||||
p1 = FSCollector('proj/test/a', parent=p0)
|
||||
p2 = Node('B', parent=p1)
|
||||
p3 = Node('()', parent = p2)
|
||||
p3 = Node('()', parent=p2)
|
||||
p4 = Node('c', parent=p3)
|
||||
item = Item('[1]', parent = p4)
|
||||
item = Item('[1]', parent=p4)
|
||||
|
||||
res = generic_path(item)
|
||||
assert res == 'test/a:B().c[1]'
|
||||
|
||||
|
||||
def test_write_log_entry():
|
||||
reslog = ResultLog(None, None)
|
||||
reslog.logfile = py.io.TextIO()
|
||||
|
@ -68,7 +69,7 @@ def test_write_log_entry():
|
|||
entry_lines = entry.splitlines()
|
||||
assert len(entry_lines) == 5
|
||||
assert entry_lines[0] == 'F name'
|
||||
assert entry_lines[1:] == [' '+line for line in longrepr.splitlines()]
|
||||
assert entry_lines[1:] == [' ' + line for line in longrepr.splitlines()]
|
||||
|
||||
|
||||
class TestWithFunctionIntegration(object):
|
||||
|
@ -144,7 +145,7 @@ class TestWithFunctionIntegration(object):
|
|||
|
||||
assert entry_lines[0].startswith('! ')
|
||||
if style != "native":
|
||||
assert os.path.basename(__file__)[:-9] in entry_lines[0] #.pyc/class
|
||||
assert os.path.basename(__file__)[:-9] in entry_lines[0] # .pyc/class
|
||||
assert entry_lines[-1][0] == ' '
|
||||
assert 'ValueError' in entry
|
||||
|
||||
|
@ -176,6 +177,7 @@ def test_generic(testdir, LineMatcher):
|
|||
"x *:test_xfail_norun",
|
||||
])
|
||||
|
||||
|
||||
def test_makedir_for_resultlog(testdir, LineMatcher):
|
||||
"""--resultlog should automatically create directories for the log file"""
|
||||
testdir.plugins.append("resultlog")
|
||||
|
@ -224,5 +226,3 @@ def test_failure_issue380(testdir):
|
|||
""")
|
||||
result = testdir.runpytest("--resultlog=log")
|
||||
assert result.ret == 2
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import pytest
|
|||
import sys
|
||||
from _pytest import runner, main
|
||||
|
||||
|
||||
class TestSetupState(object):
|
||||
def test_setup(self, testdir):
|
||||
ss = runner.SetupState()
|
||||
|
@ -31,7 +32,7 @@ class TestSetupState(object):
|
|||
def setup_module(mod):
|
||||
raise ValueError(42)
|
||||
def test_func(): pass
|
||||
""") # noqa
|
||||
""") # noqa
|
||||
ss = runner.SetupState()
|
||||
pytest.raises(ValueError, lambda: ss.prepare(item))
|
||||
pytest.raises(ValueError, lambda: ss.prepare(item))
|
||||
|
@ -39,11 +40,14 @@ class TestSetupState(object):
|
|||
def test_teardown_multiple_one_fails(self, testdir):
|
||||
r = []
|
||||
|
||||
def fin1(): r.append('fin1')
|
||||
def fin1():
|
||||
r.append('fin1')
|
||||
|
||||
def fin2(): raise Exception('oops')
|
||||
def fin2():
|
||||
raise Exception('oops')
|
||||
|
||||
def fin3(): r.append('fin3')
|
||||
def fin3():
|
||||
r.append('fin3')
|
||||
|
||||
item = testdir.getitem("def test_func(): pass")
|
||||
ss = runner.SetupState()
|
||||
|
@ -58,9 +62,11 @@ class TestSetupState(object):
|
|||
def test_teardown_multiple_fail(self, testdir):
|
||||
# Ensure the first exception is the one which is re-raised.
|
||||
# Ideally both would be reported however.
|
||||
def fin1(): raise Exception('oops1')
|
||||
def fin1():
|
||||
raise Exception('oops1')
|
||||
|
||||
def fin2(): raise Exception('oops2')
|
||||
def fin2():
|
||||
raise Exception('oops2')
|
||||
|
||||
item = testdir.getitem("def test_func(): pass")
|
||||
ss = runner.SetupState()
|
||||
|
@ -94,7 +100,7 @@ class BaseFunctionalTests(object):
|
|||
assert rep.failed
|
||||
assert rep.when == "call"
|
||||
assert rep.outcome == "failed"
|
||||
#assert isinstance(rep.longrepr, ReprExceptionInfo)
|
||||
# assert isinstance(rep.longrepr, ReprExceptionInfo)
|
||||
|
||||
def test_skipfunction(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
|
@ -107,12 +113,12 @@ class BaseFunctionalTests(object):
|
|||
assert not rep.passed
|
||||
assert rep.skipped
|
||||
assert rep.outcome == "skipped"
|
||||
#assert rep.skipped.when == "call"
|
||||
#assert rep.skipped.when == "call"
|
||||
#assert rep.skipped == "%sreason == "hello"
|
||||
#assert rep.skipped.location.lineno == 3
|
||||
#assert rep.skipped.location.path
|
||||
#assert not rep.skipped.failurerepr
|
||||
# assert rep.skipped.when == "call"
|
||||
# assert rep.skipped.when == "call"
|
||||
# assert rep.skipped == "%sreason == "hello"
|
||||
# assert rep.skipped.location.lineno == 3
|
||||
# assert rep.skipped.location.path
|
||||
# assert not rep.skipped.failurerepr
|
||||
|
||||
def test_skip_in_setup_function(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
|
@ -127,11 +133,11 @@ class BaseFunctionalTests(object):
|
|||
assert not rep.failed
|
||||
assert not rep.passed
|
||||
assert rep.skipped
|
||||
#assert rep.skipped.reason == "hello"
|
||||
#assert rep.skipped.location.lineno == 3
|
||||
#assert rep.skipped.location.lineno == 3
|
||||
# assert rep.skipped.reason == "hello"
|
||||
# assert rep.skipped.location.lineno == 3
|
||||
# assert rep.skipped.location.lineno == 3
|
||||
assert len(reports) == 2
|
||||
assert reports[1].passed # teardown
|
||||
assert reports[1].passed # teardown
|
||||
|
||||
def test_failure_in_setup_function(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
|
@ -163,8 +169,8 @@ class BaseFunctionalTests(object):
|
|||
assert not rep.passed
|
||||
assert rep.failed
|
||||
assert rep.when == "teardown"
|
||||
#assert rep.longrepr.reprcrash.lineno == 3
|
||||
#assert rep.longrepr.reprtraceback.reprentries
|
||||
# assert rep.longrepr.reprcrash.lineno == 3
|
||||
# assert rep.longrepr.reprtraceback.reprentries
|
||||
|
||||
def test_custom_failure_repr(self, testdir):
|
||||
testdir.makepyfile(conftest="""
|
||||
|
@ -182,10 +188,10 @@ class BaseFunctionalTests(object):
|
|||
assert not rep.skipped
|
||||
assert not rep.passed
|
||||
assert rep.failed
|
||||
#assert rep.outcome.when == "call"
|
||||
#assert rep.failed.where.lineno == 3
|
||||
#assert rep.failed.where.path.basename == "test_func.py"
|
||||
#assert rep.failed.failurerepr == "hello"
|
||||
# assert rep.outcome.when == "call"
|
||||
# assert rep.failed.where.lineno == 3
|
||||
# assert rep.failed.where.path.basename == "test_func.py"
|
||||
# assert rep.failed.failurerepr == "hello"
|
||||
|
||||
def test_teardown_final_returncode(self, testdir):
|
||||
rec = testdir.inline_runsource("""
|
||||
|
@ -227,7 +233,7 @@ class BaseFunctionalTests(object):
|
|||
assert reps[2].when == "teardown"
|
||||
assert reps[2].failed
|
||||
assert len(reps) == 6
|
||||
for i in range(3,5):
|
||||
for i in range(3, 5):
|
||||
assert reps[i].nodeid.endswith("test_func")
|
||||
assert reps[i].passed
|
||||
assert reps[5].when == "teardown"
|
||||
|
@ -262,11 +268,11 @@ class BaseFunctionalTests(object):
|
|||
assert reps[2].failed
|
||||
assert reps[2].when == "teardown"
|
||||
assert reps[2].longrepr.reprcrash.message in (
|
||||
# python3 error
|
||||
"TypeError: teardown_method() missing 2 required positional arguments: 'y' and 'z'",
|
||||
# python2 error
|
||||
'TypeError: teardown_method() takes exactly 4 arguments (2 given)'
|
||||
)
|
||||
# python3 error
|
||||
"TypeError: teardown_method() missing 2 required positional arguments: 'y' and 'z'",
|
||||
# python2 error
|
||||
'TypeError: teardown_method() takes exactly 4 arguments (2 given)'
|
||||
)
|
||||
|
||||
def test_failure_in_setup_function_ignores_custom_repr(self, testdir):
|
||||
testdir.makepyfile(conftest="""
|
||||
|
@ -287,10 +293,10 @@ class BaseFunctionalTests(object):
|
|||
assert not rep.skipped
|
||||
assert not rep.passed
|
||||
assert rep.failed
|
||||
#assert rep.outcome.when == "setup"
|
||||
#assert rep.outcome.where.lineno == 3
|
||||
#assert rep.outcome.where.path.basename == "test_func.py"
|
||||
#assert instanace(rep.failed.failurerepr, PythonFailureRepr)
|
||||
# assert rep.outcome.when == "setup"
|
||||
# assert rep.outcome.where.lineno == 3
|
||||
# assert rep.outcome.where.path.basename == "test_func.py"
|
||||
# assert instanace(rep.failed.failurerepr, PythonFailureRepr)
|
||||
|
||||
def test_systemexit_does_not_bail_out(self, testdir):
|
||||
try:
|
||||
|
@ -316,6 +322,7 @@ class BaseFunctionalTests(object):
|
|||
else:
|
||||
pytest.fail("did not raise")
|
||||
|
||||
|
||||
class TestExecutionNonForked(BaseFunctionalTests):
|
||||
def getrunner(self):
|
||||
def f(item):
|
||||
|
@ -333,6 +340,7 @@ class TestExecutionNonForked(BaseFunctionalTests):
|
|||
else:
|
||||
pytest.fail("did not raise")
|
||||
|
||||
|
||||
class TestExecutionForked(BaseFunctionalTests):
|
||||
pytestmark = pytest.mark.skipif("not hasattr(os, 'fork')")
|
||||
|
||||
|
@ -351,6 +359,7 @@ class TestExecutionForked(BaseFunctionalTests):
|
|||
assert rep.failed
|
||||
assert rep.when == "???"
|
||||
|
||||
|
||||
class TestSessionReports(object):
|
||||
def test_collect_result(self, testdir):
|
||||
col = testdir.getmodulecol("""
|
||||
|
@ -380,6 +389,7 @@ reporttypes = [
|
|||
runner.CollectReport,
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes])
|
||||
def test_report_extra_parameters(reporttype):
|
||||
if hasattr(py.std.inspect, 'signature'):
|
||||
|
@ -390,12 +400,13 @@ def test_report_extra_parameters(reporttype):
|
|||
report = reporttype(newthing=1, **basekw)
|
||||
assert report.newthing == 1
|
||||
|
||||
|
||||
def test_callinfo():
|
||||
ci = runner.CallInfo(lambda: 0, '123')
|
||||
assert ci.when == "123"
|
||||
assert ci.result == 0
|
||||
assert "result" in repr(ci)
|
||||
ci = runner.CallInfo(lambda: 0/0, '123')
|
||||
ci = runner.CallInfo(lambda: 0 / 0, '123')
|
||||
assert ci.when == "123"
|
||||
assert not hasattr(ci, 'result')
|
||||
assert ci.excinfo
|
||||
|
@ -403,6 +414,8 @@ def test_callinfo():
|
|||
|
||||
# design question: do we want general hooks in python files?
|
||||
# then something like the following functional tests makes sense
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
def test_runtest_in_module_ordering(testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
|
@ -439,6 +452,7 @@ def test_outcomeexception_exceptionattributes():
|
|||
outcome = runner.OutcomeException('test')
|
||||
assert outcome.args[0] == outcome.msg
|
||||
|
||||
|
||||
def test_pytest_exit():
|
||||
try:
|
||||
pytest.exit("hello")
|
||||
|
@ -446,6 +460,7 @@ def test_pytest_exit():
|
|||
excinfo = _pytest._code.ExceptionInfo()
|
||||
assert excinfo.errisinstance(KeyboardInterrupt)
|
||||
|
||||
|
||||
def test_pytest_fail():
|
||||
try:
|
||||
pytest.fail("hello")
|
||||
|
@ -454,6 +469,7 @@ def test_pytest_fail():
|
|||
s = excinfo.exconly(tryshort=True)
|
||||
assert s.startswith("Failed")
|
||||
|
||||
|
||||
def test_pytest_exit_msg(testdir):
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
|
@ -466,6 +482,7 @@ def test_pytest_exit_msg(testdir):
|
|||
"Exit: oh noes",
|
||||
])
|
||||
|
||||
|
||||
def test_pytest_fail_notrace(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -531,6 +548,7 @@ def test_exception_printing_skip():
|
|||
s = excinfo.exconly(tryshort=True)
|
||||
assert s.startswith("Skipped")
|
||||
|
||||
|
||||
def test_importorskip(monkeypatch):
|
||||
importorskip = pytest.importorskip
|
||||
|
||||
|
@ -540,8 +558,8 @@ def test_importorskip(monkeypatch):
|
|||
try:
|
||||
sys = importorskip("sys") # noqa
|
||||
assert sys == py.std.sys
|
||||
#path = pytest.importorskip("os.path")
|
||||
#assert path == py.std.os.path
|
||||
# path = pytest.importorskip("os.path")
|
||||
# assert path == py.std.os.path
|
||||
excinfo = pytest.raises(pytest.skip.Exception, f)
|
||||
path = py.path.local(excinfo.getrepr().reprcrash.path)
|
||||
# check that importorskip reports the actual call
|
||||
|
@ -561,10 +579,12 @@ def test_importorskip(monkeypatch):
|
|||
print(_pytest._code.ExceptionInfo())
|
||||
pytest.fail("spurious skip")
|
||||
|
||||
|
||||
def test_importorskip_imports_last_module_part():
|
||||
ospath = pytest.importorskip("os.path")
|
||||
assert os.path == ospath
|
||||
|
||||
|
||||
def test_importorskip_dev_module(monkeypatch):
|
||||
try:
|
||||
mod = py.std.types.ModuleType("mockmodule")
|
||||
|
@ -754,5 +774,3 @@ class TestReportContents(object):
|
|||
rep = reports[1]
|
||||
assert rep.capstdout == ''
|
||||
assert rep.capstderr == ''
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ def test_module_and_function_setup(testdir):
|
|||
rep = reprec.matchreport("test_module")
|
||||
assert rep.passed
|
||||
|
||||
|
||||
def test_module_setup_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
l = []
|
||||
|
@ -53,6 +54,7 @@ def test_module_setup_failure_no_teardown(testdir):
|
|||
calls = reprec.getcalls("pytest_runtest_setup")
|
||||
assert calls[0].item.module.l == [1]
|
||||
|
||||
|
||||
def test_setup_function_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
modlevel = []
|
||||
|
@ -69,6 +71,7 @@ def test_setup_function_failure_no_teardown(testdir):
|
|||
calls = reprec.getcalls("pytest_runtest_setup")
|
||||
assert calls[0].item.module.modlevel == [1]
|
||||
|
||||
|
||||
def test_class_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
class TestSimpleClassSetup(object):
|
||||
|
@ -90,7 +93,8 @@ def test_class_setup(testdir):
|
|||
assert not TestSimpleClassSetup.clslevel
|
||||
assert not TestInheritedClassSetupStillWorks.clslevel
|
||||
""")
|
||||
reprec.assertoutcome(passed=1+2+1)
|
||||
reprec.assertoutcome(passed=1 + 2 + 1)
|
||||
|
||||
|
||||
def test_class_setup_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
|
@ -110,6 +114,7 @@ def test_class_setup_failure_no_teardown(testdir):
|
|||
""")
|
||||
reprec.assertoutcome(failed=1, passed=1)
|
||||
|
||||
|
||||
def test_method_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
class TestSetupMethod(object):
|
||||
|
@ -126,6 +131,7 @@ def test_method_setup(testdir):
|
|||
""")
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
def test_method_setup_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
class TestMethodSetup(object):
|
||||
|
@ -145,6 +151,7 @@ def test_method_setup_failure_no_teardown(testdir):
|
|||
""")
|
||||
reprec.assertoutcome(failed=1, passed=1)
|
||||
|
||||
|
||||
def test_method_generator_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
class TestSetupTeardownOnInstance(object):
|
||||
|
@ -167,6 +174,7 @@ def test_method_generator_setup(testdir):
|
|||
""")
|
||||
reprec.assertoutcome(passed=1, failed=1)
|
||||
|
||||
|
||||
def test_func_generator_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
import sys
|
||||
|
@ -195,6 +203,7 @@ def test_func_generator_setup(testdir):
|
|||
rep = reprec.matchreport("test_one", names="pytest_runtest_logreport")
|
||||
assert rep.passed
|
||||
|
||||
|
||||
def test_method_setup_uses_fresh_instances(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
class TestSelfState1(object):
|
||||
|
@ -207,6 +216,7 @@ def test_method_setup_uses_fresh_instances(testdir):
|
|||
""")
|
||||
reprec.assertoutcome(passed=2, failed=0)
|
||||
|
||||
|
||||
def test_setup_that_skips_calledagain(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -220,6 +230,7 @@ def test_setup_that_skips_calledagain(testdir):
|
|||
reprec = testdir.inline_run(p)
|
||||
reprec.assertoutcome(skipped=2)
|
||||
|
||||
|
||||
def test_setup_fails_again_on_all_tests(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -233,6 +244,7 @@ def test_setup_fails_again_on_all_tests(testdir):
|
|||
reprec = testdir.inline_run(p)
|
||||
reprec.assertoutcome(failed=2)
|
||||
|
||||
|
||||
def test_setup_funcarg_setup_when_outer_scope_fails(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import pytest
|
||||
|
|
|
@ -3,6 +3,7 @@ import pytest
|
|||
|
||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
class SessionTests(object):
|
||||
def test_basic_testitem_events(self, testdir):
|
||||
tfile = testdir.makepyfile("""
|
||||
|
@ -21,15 +22,18 @@ class SessionTests(object):
|
|||
assert len(skipped) == 0
|
||||
assert len(passed) == 1
|
||||
assert len(failed) == 3
|
||||
end = lambda x: x.nodeid.split("::")[-1]
|
||||
|
||||
def end(x):
|
||||
return x.nodeid.split("::")[-1]
|
||||
|
||||
assert end(failed[0]) == "test_one_one"
|
||||
assert end(failed[1]) == "test_other"
|
||||
itemstarted = reprec.getcalls("pytest_itemcollected")
|
||||
assert len(itemstarted) == 4
|
||||
# XXX check for failing funcarg setup
|
||||
#colreports = reprec.getcalls("pytest_collectreport")
|
||||
#assert len(colreports) == 4
|
||||
#assert colreports[1].report.failed
|
||||
# colreports = reprec.getcalls("pytest_collectreport")
|
||||
# assert len(colreports) == 4
|
||||
# assert colreports[1].report.failed
|
||||
|
||||
def test_nested_import_error(self, testdir):
|
||||
tfile = testdir.makepyfile("""
|
||||
|
@ -117,7 +121,7 @@ class SessionTests(object):
|
|||
passed, skipped, failed = reprec.listoutcomes()
|
||||
assert len(failed) == 1
|
||||
out = failed[0].longrepr.reprcrash.message
|
||||
assert out.find("""[Exception("Ha Ha fooled you, I'm a broken repr().") raised in repr()]""") != -1 #'
|
||||
assert out.find("""[Exception("Ha Ha fooled you, I'm a broken repr().") raised in repr()]""") != -1 # '
|
||||
|
||||
def test_skip_file_by_conftest(self, testdir):
|
||||
testdir.makepyfile(conftest="""
|
||||
|
@ -135,6 +139,7 @@ class SessionTests(object):
|
|||
assert len(reports) == 1
|
||||
assert reports[0].skipped
|
||||
|
||||
|
||||
class TestNewSession(SessionTests):
|
||||
|
||||
def test_order_of_execution(self, testdir):
|
||||
|
@ -186,7 +191,7 @@ class TestNewSession(SessionTests):
|
|||
started = reprec.getcalls("pytest_collectstart")
|
||||
finished = reprec.getreports("pytest_collectreport")
|
||||
assert len(started) == len(finished)
|
||||
assert len(started) == 7 # XXX extra TopCollector
|
||||
assert len(started) == 7 # XXX extra TopCollector
|
||||
colfail = [x for x in finished if x.failed]
|
||||
assert len(colfail) == 1
|
||||
|
||||
|
@ -211,9 +216,10 @@ def test_plugin_specify(testdir):
|
|||
pytest.raises(ImportError, """
|
||||
testdir.parseconfig("-p", "nqweotexistent")
|
||||
""")
|
||||
#pytest.raises(ImportError,
|
||||
# pytest.raises(ImportError,
|
||||
# "config.do_configure(config)"
|
||||
#)
|
||||
# )
|
||||
|
||||
|
||||
def test_plugin_already_exists(testdir):
|
||||
config = testdir.parseconfig("-p", "terminal")
|
||||
|
@ -221,6 +227,7 @@ def test_plugin_already_exists(testdir):
|
|||
config._do_configure()
|
||||
config._ensure_unconfigure()
|
||||
|
||||
|
||||
def test_exclude(testdir):
|
||||
hellodir = testdir.mkdir("hello")
|
||||
hellodir.join("test_hello.py").write("x y syntaxerror")
|
||||
|
@ -231,6 +238,7 @@ def test_exclude(testdir):
|
|||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
def test_sessionfinish_with_start(testdir):
|
||||
testdir.makeconftest("""
|
||||
import os
|
||||
|
|
|
@ -80,7 +80,7 @@ class TestEvaluator(object):
|
|||
%s
|
||||
def test_func():
|
||||
pass
|
||||
""" % (lines[i], lines[(i+1) %2]))
|
||||
""" % (lines[i], lines[(i + 1) % 2]))
|
||||
ev = MarkEvaluator(item, 'skipif')
|
||||
assert ev
|
||||
assert ev.istrue()
|
||||
|
@ -207,9 +207,9 @@ class TestXFail(object):
|
|||
assert 0
|
||||
""")
|
||||
testdir.runpytest(p, '-v')
|
||||
#result.stdout.fnmatch_lines([
|
||||
# result.stdout.fnmatch_lines([
|
||||
# "*HINT*use*-r*"
|
||||
#])
|
||||
# ])
|
||||
|
||||
def test_xfail_not_run_xfail_reporting(self, testdir):
|
||||
p = testdir.makepyfile(test_one="""
|
||||
|
@ -350,7 +350,6 @@ class TestXFail(object):
|
|||
"*1 xfailed*",
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('expected, actual, matchline',
|
||||
[('TypeError', 'TypeError', "*1 xfailed*"),
|
||||
('(AttributeError, TypeError)', 'TypeError', "*1 xfailed*"),
|
||||
|
@ -582,6 +581,7 @@ class TestSkip(object):
|
|||
"*1 skipped*",
|
||||
])
|
||||
|
||||
|
||||
class TestSkipif(object):
|
||||
def test_skipif_conditional(self, testdir):
|
||||
item = testdir.getitem("""
|
||||
|
@ -589,7 +589,7 @@ class TestSkipif(object):
|
|||
@pytest.mark.skipif("hasattr(os, 'sep')")
|
||||
def test_func():
|
||||
pass
|
||||
""") # noqa
|
||||
""") # noqa
|
||||
x = pytest.raises(pytest.skip.Exception, lambda:
|
||||
pytest_runtest_setup(item))
|
||||
assert x.value.msg == "condition: hasattr(os, 'sep')"
|
||||
|
@ -640,7 +640,7 @@ def test_skip_not_report_default(testdir):
|
|||
""")
|
||||
result = testdir.runpytest(p, '-v')
|
||||
result.stdout.fnmatch_lines([
|
||||
#"*HINT*use*-r*",
|
||||
# "*HINT*use*-r*",
|
||||
"*1 skipped*",
|
||||
])
|
||||
|
||||
|
@ -687,6 +687,7 @@ def test_skip_reasons_folding():
|
|||
assert lineno == lineno
|
||||
assert reason == message
|
||||
|
||||
|
||||
def test_skipped_reasons_functional(testdir):
|
||||
testdir.makepyfile(
|
||||
test_one="""
|
||||
|
@ -699,7 +700,7 @@ def test_skipped_reasons_functional(testdir):
|
|||
def test_method(self):
|
||||
doskip()
|
||||
""",
|
||||
conftest = """
|
||||
conftest="""
|
||||
import pytest
|
||||
def doskip():
|
||||
pytest.skip('test')
|
||||
|
@ -711,6 +712,7 @@ def test_skipped_reasons_functional(testdir):
|
|||
])
|
||||
assert result.ret == 0
|
||||
|
||||
|
||||
def test_reportchars(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -733,6 +735,7 @@ def test_reportchars(testdir):
|
|||
"SKIP*four*",
|
||||
])
|
||||
|
||||
|
||||
def test_reportchars_error(testdir):
|
||||
testdir.makepyfile(
|
||||
conftest="""
|
||||
|
@ -748,6 +751,7 @@ def test_reportchars_error(testdir):
|
|||
'ERROR*test_foo*',
|
||||
])
|
||||
|
||||
|
||||
def test_reportchars_all(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -770,6 +774,7 @@ def test_reportchars_all(testdir):
|
|||
"XPASS*test_3*",
|
||||
])
|
||||
|
||||
|
||||
def test_reportchars_all_error(testdir):
|
||||
testdir.makepyfile(
|
||||
conftest="""
|
||||
|
@ -785,6 +790,7 @@ def test_reportchars_all_error(testdir):
|
|||
'ERROR*test_foo*',
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.xfail("hasattr(sys, 'pypy_version_info')")
|
||||
def test_errors_in_xfail_skip_expressions(testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -816,6 +822,7 @@ def test_errors_in_xfail_skip_expressions(testdir):
|
|||
"*1 pass*2 error*",
|
||||
])
|
||||
|
||||
|
||||
def test_xfail_skipif_with_globals(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -834,6 +841,7 @@ def test_xfail_skipif_with_globals(testdir):
|
|||
"*x == 3*",
|
||||
])
|
||||
|
||||
|
||||
def test_direct_gives_error(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -854,6 +862,7 @@ def test_default_markers(testdir):
|
|||
"*xfail(*condition, reason=None, run=True, raises=None, strict=False)*expected failure*",
|
||||
])
|
||||
|
||||
|
||||
def test_xfail_test_setup_exception(testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_runtest_setup():
|
||||
|
@ -870,6 +879,7 @@ def test_xfail_test_setup_exception(testdir):
|
|||
assert 'xfailed' in result.stdout.str()
|
||||
assert 'xpassed' not in result.stdout.str()
|
||||
|
||||
|
||||
def test_imperativeskip_on_xfail_test(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -893,6 +903,7 @@ def test_imperativeskip_on_xfail_test(testdir):
|
|||
*2 skipped*
|
||||
""")
|
||||
|
||||
|
||||
class TestBooleanCondition(object):
|
||||
def test_skipif(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
|
|
@ -31,6 +31,7 @@ class Option(object):
|
|||
l.append('--fulltrace')
|
||||
return l
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if "option" in metafunc.fixturenames:
|
||||
metafunc.addcall(id="default",
|
||||
|
@ -38,7 +39,7 @@ def pytest_generate_tests(metafunc):
|
|||
metafunc.addcall(id="verbose",
|
||||
funcargs={'option': Option(verbose=True)})
|
||||
metafunc.addcall(id="quiet",
|
||||
funcargs={'option': Option(verbose= -1)})
|
||||
funcargs={'option': Option(verbose=-1)})
|
||||
metafunc.addcall(id="fulltrace",
|
||||
funcargs={'option': Option(fulltrace=True)})
|
||||
|
||||
|
@ -77,8 +78,8 @@ class TestTerminal(object):
|
|||
])
|
||||
else:
|
||||
result.stdout.fnmatch_lines([
|
||||
"*test_pass_skip_fail.py .sF"
|
||||
])
|
||||
"*test_pass_skip_fail.py .sF"
|
||||
])
|
||||
result.stdout.fnmatch_lines([
|
||||
" def test_func():",
|
||||
"> assert 0",
|
||||
|
@ -110,7 +111,7 @@ class TestTerminal(object):
|
|||
item.config.pluginmanager.register(tr)
|
||||
location = item.reportinfo()
|
||||
tr.config.hook.pytest_runtest_logstart(nodeid=item.nodeid,
|
||||
location=location, fspath=str(item.fspath))
|
||||
location=location, fspath=str(item.fspath))
|
||||
linecomp.assert_contains_lines([
|
||||
"*test_show_runtest_logstart.py*"
|
||||
])
|
||||
|
@ -222,8 +223,8 @@ class TestCollectonly(object):
|
|||
""")
|
||||
result = testdir.runpytest("--collect-only",)
|
||||
result.stdout.fnmatch_lines([
|
||||
"<Module 'test_collectonly_basic.py'>",
|
||||
" <Function 'test_func'>",
|
||||
"<Module 'test_collectonly_basic.py'>",
|
||||
" <Function 'test_func'>",
|
||||
])
|
||||
|
||||
def test_collectonly_skipped_module(self, testdir):
|
||||
|
@ -264,13 +265,13 @@ class TestCollectonly(object):
|
|||
pass
|
||||
""")
|
||||
result = testdir.runpytest("--collect-only", p)
|
||||
#assert stderr.startswith("inserting into sys.path")
|
||||
# assert stderr.startswith("inserting into sys.path")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*<Module '*.py'>",
|
||||
"* <Function 'test_func1'*>",
|
||||
"* <Class 'TestClass'>",
|
||||
#"* <Instance '()'>",
|
||||
# "* <Instance '()'>",
|
||||
"* <Function 'test_method'*>",
|
||||
])
|
||||
|
||||
|
@ -318,7 +319,8 @@ def test_repr_python_version(monkeypatch):
|
|||
py.std.sys.version_info = x = (2, 3)
|
||||
assert repr_pythonversion() == str(x)
|
||||
finally:
|
||||
monkeypatch.undo() # do this early as pytest can get confused
|
||||
monkeypatch.undo() # do this early as pytest can get confused
|
||||
|
||||
|
||||
class TestFixtureReporting(object):
|
||||
def test_setup_fixture_error(self, testdir):
|
||||
|
@ -378,7 +380,7 @@ class TestFixtureReporting(object):
|
|||
"*def test_fail():",
|
||||
"*failingfunc*",
|
||||
"*1 failed*1 error*",
|
||||
])
|
||||
])
|
||||
|
||||
def test_setup_teardown_output_and_test_failure(self, testdir):
|
||||
""" Test for issue #442 """
|
||||
|
@ -403,7 +405,8 @@ class TestFixtureReporting(object):
|
|||
"*teardown func*",
|
||||
|
||||
"*1 failed*",
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
class TestTerminalFunctional(object):
|
||||
def test_deselected(self, testdir):
|
||||
|
@ -415,7 +418,7 @@ class TestTerminalFunctional(object):
|
|||
def test_three():
|
||||
pass
|
||||
"""
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest("-k", "test_two:", testpath)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*test_deselected.py ..",
|
||||
|
@ -485,7 +488,7 @@ class TestTerminalFunctional(object):
|
|||
""")
|
||||
result = testdir.runpytest(p1, '-l')
|
||||
result.stdout.fnmatch_lines([
|
||||
#"_ _ * Locals *",
|
||||
# "_ _ * Locals *",
|
||||
"x* = 3",
|
||||
"y* = 'xxxxxx*"
|
||||
])
|
||||
|
@ -552,11 +555,13 @@ def test_fail_extra_reporting(testdir):
|
|||
"FAIL*test_fail_extra_reporting*",
|
||||
])
|
||||
|
||||
|
||||
def test_fail_reporting_on_pass(testdir):
|
||||
testdir.makepyfile("def test_this(): assert 1")
|
||||
result = testdir.runpytest('-rf')
|
||||
assert 'short test summary' not in result.stdout.str()
|
||||
|
||||
|
||||
def test_pass_extra_reporting(testdir):
|
||||
testdir.makepyfile("def test_this(): assert 1")
|
||||
result = testdir.runpytest()
|
||||
|
@ -567,11 +572,13 @@ def test_pass_extra_reporting(testdir):
|
|||
"PASS*test_pass_extra_reporting*",
|
||||
])
|
||||
|
||||
|
||||
def test_pass_reporting_on_fail(testdir):
|
||||
testdir.makepyfile("def test_this(): assert 0")
|
||||
result = testdir.runpytest('-rp')
|
||||
assert 'short test summary' not in result.stdout.str()
|
||||
|
||||
|
||||
def test_pass_output_reporting(testdir):
|
||||
testdir.makepyfile("""
|
||||
def test_pass_output():
|
||||
|
@ -584,6 +591,7 @@ def test_pass_output_reporting(testdir):
|
|||
"Four score and seven years ago...",
|
||||
])
|
||||
|
||||
|
||||
def test_color_yes(testdir):
|
||||
testdir.makepyfile("def test_this(): assert 1")
|
||||
result = testdir.runpytest('--color=yes')
|
||||
|
@ -660,6 +668,7 @@ def test_terminalreporter_reportopt_addopts(testdir):
|
|||
"*1 passed*"
|
||||
])
|
||||
|
||||
|
||||
def test_tbstyle_short(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -685,6 +694,7 @@ def test_tbstyle_short(testdir):
|
|||
assert 'x = 0' in s
|
||||
assert 'assert x' in s
|
||||
|
||||
|
||||
def test_traceconfig(testdir, monkeypatch):
|
||||
result = testdir.runpytest("--traceconfig")
|
||||
result.stdout.fnmatch_lines([
|
||||
|
@ -697,6 +707,7 @@ class TestGenericReporting(object):
|
|||
""" this test class can be subclassed with a different option
|
||||
provider to run e.g. distributed tests.
|
||||
"""
|
||||
|
||||
def test_collect_fail(self, testdir, option):
|
||||
testdir.makepyfile("import xyz\n")
|
||||
result = testdir.runpytest(*option.args)
|
||||
|
@ -723,7 +734,6 @@ class TestGenericReporting(object):
|
|||
"*2 failed*",
|
||||
])
|
||||
|
||||
|
||||
def test_tb_option(self, testdir, option):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -787,6 +797,7 @@ def pytest_report_header(config, startdir):
|
|||
str(testdir.tmpdir),
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.xfail("not hasattr(os, 'dup')")
|
||||
def test_fdopen_kept_alive_issue124(testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -805,6 +816,7 @@ def test_fdopen_kept_alive_issue124(testdir):
|
|||
"*2 passed*"
|
||||
])
|
||||
|
||||
|
||||
def test_tbstyle_native_setup_error(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -817,8 +829,9 @@ def test_tbstyle_native_setup_error(testdir):
|
|||
""")
|
||||
result = testdir.runpytest("--tb=native")
|
||||
result.stdout.fnmatch_lines([
|
||||
'*File *test_tbstyle_native_setup_error.py", line *, in setup_error_fixture*'
|
||||
])
|
||||
'*File *test_tbstyle_native_setup_error.py", line *, in setup_error_fixture*'
|
||||
])
|
||||
|
||||
|
||||
def test_terminal_summary(testdir):
|
||||
testdir.makeconftest("""
|
||||
|
@ -872,7 +885,7 @@ def test_terminal_summary_warnings_are_displayed(testdir):
|
|||
("yellow", "1 passed, 1 warnings", {"warnings": (1,),
|
||||
"passed": (1,)}),
|
||||
|
||||
("green", "5 passed", {"passed": (1,2,3,4,5)}),
|
||||
("green", "5 passed", {"passed": (1, 2, 3, 4, 5)}),
|
||||
|
||||
|
||||
# "Boring" statuses. These have no effect on the color of the summary
|
||||
|
@ -901,13 +914,13 @@ def test_terminal_summary_warnings_are_displayed(testdir):
|
|||
|
||||
# A couple more complex combinations
|
||||
("red", "1 failed, 2 passed, 3 xfailed",
|
||||
{"passed": (1,2), "failed": (1,), "xfailed": (1,2,3)}),
|
||||
{"passed": (1, 2), "failed": (1,), "xfailed": (1, 2, 3)}),
|
||||
|
||||
("green", "1 passed, 2 skipped, 3 deselected, 2 xfailed",
|
||||
{"passed": (1,),
|
||||
"skipped": (1,2),
|
||||
"deselected": (1,2,3),
|
||||
"xfailed": (1,2)}),
|
||||
"skipped": (1, 2),
|
||||
"deselected": (1, 2, 3),
|
||||
"xfailed": (1, 2)}),
|
||||
])
|
||||
def test_summary_stats(exp_line, exp_color, stats_arg):
|
||||
print("Based on stats: %s" % stats_arg)
|
||||
|
|
|
@ -5,6 +5,7 @@ import pytest
|
|||
|
||||
from _pytest.tmpdir import tmpdir
|
||||
|
||||
|
||||
def test_funcarg(testdir):
|
||||
testdir.makepyfile("""
|
||||
def pytest_generate_tests(metafunc):
|
||||
|
@ -29,12 +30,14 @@ def test_funcarg(testdir):
|
|||
bn = p.basename.strip("0123456789")
|
||||
assert bn == "qwe__abc"
|
||||
|
||||
|
||||
def test_ensuretemp(recwarn):
|
||||
d1 = pytest.ensuretemp('hello')
|
||||
d2 = pytest.ensuretemp('hello')
|
||||
assert d1 == d2
|
||||
assert d1.check(dir=1)
|
||||
|
||||
|
||||
class TestTempdirHandler(object):
|
||||
def test_mktemp(self, testdir):
|
||||
from _pytest.tmpdir import TempdirFactory
|
||||
|
@ -49,6 +52,7 @@ class TestTempdirHandler(object):
|
|||
assert tmp2.relto(t.getbasetemp()).startswith("this")
|
||||
assert tmp2 != tmp
|
||||
|
||||
|
||||
class TestConfigTmpdir(object):
|
||||
def test_getbasetemp_custom_removes_old(self, testdir):
|
||||
mytemp = testdir.tmpdir.join("xyz")
|
||||
|
@ -76,6 +80,7 @@ def test_basetemp(testdir):
|
|||
assert result.ret == 0
|
||||
assert mytemp.join('hello').check()
|
||||
|
||||
|
||||
@pytest.mark.skipif(not hasattr(py.path.local, 'mksymlinkto'),
|
||||
reason="symlink not available on this platform")
|
||||
def test_tmpdir_always_is_realpath(testdir):
|
||||
|
|
|
@ -3,6 +3,7 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED
|
|||
import pytest
|
||||
import gc
|
||||
|
||||
|
||||
def test_simple_unittest(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -16,6 +17,7 @@ def test_simple_unittest(testdir):
|
|||
assert reprec.matchreport("testpassing").passed
|
||||
assert reprec.matchreport("test_failing").failed
|
||||
|
||||
|
||||
def test_runTest_method(testdir):
|
||||
testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -35,6 +37,7 @@ def test_runTest_method(testdir):
|
|||
*2 passed*
|
||||
""")
|
||||
|
||||
|
||||
def test_isclasscheck_issue53(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -46,6 +49,7 @@ def test_isclasscheck_issue53(testdir):
|
|||
result = testdir.runpytest(testpath)
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_setup(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -66,6 +70,7 @@ def test_setup(testdir):
|
|||
rep = reprec.matchreport("test_both", when="teardown")
|
||||
assert rep.failed and '42' in str(rep.longrepr)
|
||||
|
||||
|
||||
def test_setUpModule(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
l = []
|
||||
|
@ -87,6 +92,7 @@ def test_setUpModule(testdir):
|
|||
"*2 passed*",
|
||||
])
|
||||
|
||||
|
||||
def test_setUpModule_failing_no_teardown(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
l = []
|
||||
|
@ -105,6 +111,7 @@ def test_setUpModule_failing_no_teardown(testdir):
|
|||
call = reprec.getcalls("pytest_runtest_setup")[0]
|
||||
assert not call.item.module.l
|
||||
|
||||
|
||||
def test_new_instances(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -117,6 +124,7 @@ def test_new_instances(testdir):
|
|||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
def test_teardown(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -136,6 +144,7 @@ def test_teardown(testdir):
|
|||
assert passed == 2
|
||||
assert passed + skipped + failed == 2
|
||||
|
||||
|
||||
def test_teardown_issue1649(testdir):
|
||||
"""
|
||||
Are TestCase objects cleaned up? Often unittest TestCase objects set
|
||||
|
@ -158,6 +167,7 @@ def test_teardown_issue1649(testdir):
|
|||
for obj in gc.get_objects():
|
||||
assert type(obj).__name__ != 'TestCaseObjectsShouldBeCleanedUp'
|
||||
|
||||
|
||||
@pytest.mark.skipif("sys.version_info < (2,7)")
|
||||
def test_unittest_skip_issue148(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
|
@ -177,6 +187,7 @@ def test_unittest_skip_issue148(testdir):
|
|||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
|
||||
def test_method_and_teardown_failing_reporting(testdir):
|
||||
testdir.makepyfile("""
|
||||
import unittest, pytest
|
||||
|
@ -196,6 +207,7 @@ def test_method_and_teardown_failing_reporting(testdir):
|
|||
"*1 failed*1 error*",
|
||||
])
|
||||
|
||||
|
||||
def test_setup_failure_is_shown(testdir):
|
||||
testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -216,6 +228,7 @@ def test_setup_failure_is_shown(testdir):
|
|||
])
|
||||
assert 'never42' not in result.stdout.str()
|
||||
|
||||
|
||||
def test_setup_setUpClass(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -238,6 +251,7 @@ def test_setup_setUpClass(testdir):
|
|||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=3)
|
||||
|
||||
|
||||
def test_setup_class(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -279,6 +293,7 @@ def test_testcase_adderrorandfailure_defers(testdir, type):
|
|||
result = testdir.runpytest()
|
||||
assert 'should not raise' not in result.stdout.str()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("type", ['Error', 'Failure'])
|
||||
def test_testcase_custom_exception_info(testdir, type):
|
||||
testdir.makepyfile("""
|
||||
|
@ -310,6 +325,7 @@ def test_testcase_custom_exception_info(testdir, type):
|
|||
"*1 failed*",
|
||||
])
|
||||
|
||||
|
||||
def test_testcase_totally_incompatible_exception_info(testdir):
|
||||
item, = testdir.getitems("""
|
||||
from unittest import TestCase
|
||||
|
@ -321,6 +337,7 @@ def test_testcase_totally_incompatible_exception_info(testdir):
|
|||
excinfo = item._excinfo.pop(0)
|
||||
assert 'ERROR: Unknown Incompatible' in str(excinfo.getrepr())
|
||||
|
||||
|
||||
def test_module_level_pytestmark(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -520,6 +537,7 @@ class TestTrialUnittest(object):
|
|||
child.expect("hellopdb")
|
||||
child.sendeof()
|
||||
|
||||
|
||||
def test_djangolike_testcase(testdir):
|
||||
# contributed from Morten Breekevold
|
||||
testdir.makepyfile("""
|
||||
|
@ -585,6 +603,7 @@ def test_unittest_not_shown_in_traceback(testdir):
|
|||
res = testdir.runpytest()
|
||||
assert "failUnlessEqual" not in res.stdout.str()
|
||||
|
||||
|
||||
def test_unorderable_types(testdir):
|
||||
testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -602,6 +621,7 @@ def test_unorderable_types(testdir):
|
|||
assert "TypeError" not in result.stdout.str()
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_unittest_typerror_traceback(testdir):
|
||||
testdir.makepyfile("""
|
||||
import unittest
|
||||
|
@ -769,6 +789,7 @@ def test_issue333_result_clearing(testdir):
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(failed=1)
|
||||
|
||||
|
||||
@pytest.mark.skipif("sys.version_info < (2,7)")
|
||||
def test_unittest_raise_skip_issue748(testdir):
|
||||
testdir.makepyfile(test_foo="""
|
||||
|
@ -784,11 +805,12 @@ def test_unittest_raise_skip_issue748(testdir):
|
|||
*1 skipped*
|
||||
""")
|
||||
|
||||
|
||||
@pytest.mark.skipif("sys.version_info < (2,7)")
|
||||
def test_unittest_skip_issue1169(testdir):
|
||||
testdir.makepyfile(test_foo="""
|
||||
import unittest
|
||||
|
||||
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@unittest.skip("skipping due to reasons")
|
||||
def test_skip(self):
|
||||
|
@ -800,6 +822,7 @@ def test_unittest_skip_issue1169(testdir):
|
|||
*1 skipped*
|
||||
""")
|
||||
|
||||
|
||||
def test_class_method_containing_test_issue1558(testdir):
|
||||
testdir.makepyfile(test_foo="""
|
||||
import unittest
|
||||
|
|
|
@ -8,6 +8,7 @@ import pytest
|
|||
|
||||
WARNINGS_SUMMARY_HEADER = 'warnings summary'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def pyfile_with_warnings(testdir, request):
|
||||
"""
|
||||
|
@ -112,7 +113,6 @@ def test_ignore(testdir, pyfile_with_warnings, method):
|
|||
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
||||
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 0),
|
||||
reason='warnings message is unicode is ok in python3')
|
||||
def test_unicode(testdir, pyfile_with_warnings):
|
||||
|
@ -173,9 +173,9 @@ def test_works_with_filterwarnings(testdir):
|
|||
|
||||
class MyWarning(Warning):
|
||||
pass
|
||||
|
||||
|
||||
warnings.filterwarnings("error", category=MyWarning)
|
||||
|
||||
|
||||
class TestWarnings(object):
|
||||
def test_my_warning(self):
|
||||
try:
|
||||
|
|
203
tox.ini
203
tox.ini
|
@ -1,53 +1,54 @@
|
|||
[tox]
|
||||
minversion=2.0
|
||||
distshare={homedir}/.tox/distshare
|
||||
minversion = 2.0
|
||||
distshare = {homedir}/.tox/distshare
|
||||
# make sure to update environment list on appveyor.yml
|
||||
envlist=
|
||||
linting
|
||||
py26
|
||||
py27
|
||||
py33
|
||||
py34
|
||||
py35
|
||||
py36
|
||||
py37
|
||||
pypy
|
||||
{py27,py35}-{pexpect,xdist,trial}
|
||||
py27-nobyte
|
||||
doctesting
|
||||
freeze
|
||||
docs
|
||||
envlist =
|
||||
linting
|
||||
py26
|
||||
py27
|
||||
py33
|
||||
py34
|
||||
py35
|
||||
py36
|
||||
py37
|
||||
pypy
|
||||
{py27,py35}-{pexpect,xdist,trial}
|
||||
py27-nobyte
|
||||
doctesting
|
||||
freeze
|
||||
docs
|
||||
|
||||
[testenv]
|
||||
commands= pytest --lsof -rfsxX {posargs:testing}
|
||||
commands = pytest --lsof -rfsxX {posargs:testing}
|
||||
passenv = USER USERNAME
|
||||
deps=
|
||||
deps =
|
||||
hypothesis>=3.5.2
|
||||
nose
|
||||
mock
|
||||
requests
|
||||
|
||||
[testenv:py26]
|
||||
commands= pytest --lsof -rfsxX {posargs:testing}
|
||||
commands = pytest --lsof -rfsxX {posargs:testing}
|
||||
# pinning mock to last supported version for python 2.6
|
||||
deps=
|
||||
deps =
|
||||
hypothesis<3.0
|
||||
nose
|
||||
mock<1.1
|
||||
|
||||
[testenv:py27-subprocess]
|
||||
changedir=.
|
||||
basepython=python2.7
|
||||
deps=pytest-xdist>=1.13
|
||||
changedir = .
|
||||
basepython = python2.7
|
||||
deps =
|
||||
pytest-xdist>=1.13
|
||||
mock
|
||||
nose
|
||||
commands=
|
||||
pytest -n3 -rfsxX --runpytest=subprocess {posargs:testing}
|
||||
commands =
|
||||
pytest -n3 -rfsxX --runpytest=subprocess {posargs:testing}
|
||||
|
||||
|
||||
[testenv:linting]
|
||||
skipsdist=True
|
||||
usedevelop=True
|
||||
skipsdist = True
|
||||
usedevelop = True
|
||||
basepython = python2.7
|
||||
# needed to keep check-manifest working
|
||||
setenv =
|
||||
|
@ -55,143 +56,145 @@ setenv =
|
|||
deps =
|
||||
flake8
|
||||
# pygments required by rst-lint
|
||||
pygments
|
||||
pygments
|
||||
restructuredtext_lint
|
||||
commands =
|
||||
flake8 pytest.py _pytest testing
|
||||
{envpython} scripts/check-rst.py
|
||||
|
||||
[testenv:py27-xdist]
|
||||
deps=pytest-xdist>=1.13
|
||||
deps =
|
||||
pytest-xdist>=1.13
|
||||
mock
|
||||
nose
|
||||
hypothesis>=3.5.2
|
||||
commands=
|
||||
pytest -n1 -rfsxX {posargs:testing}
|
||||
commands =
|
||||
pytest -n1 -rfsxX {posargs:testing}
|
||||
|
||||
[testenv:py35-xdist]
|
||||
deps={[testenv:py27-xdist]deps}
|
||||
commands=
|
||||
pytest -n3 -rfsxX {posargs:testing}
|
||||
deps = {[testenv:py27-xdist]deps}
|
||||
commands =
|
||||
pytest -n3 -rfsxX {posargs:testing}
|
||||
|
||||
[testenv:py27-pexpect]
|
||||
changedir=testing
|
||||
platform=linux|darwin
|
||||
deps=pexpect
|
||||
commands=
|
||||
pytest -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
||||
changedir = testing
|
||||
platform = linux|darwin
|
||||
deps = pexpect
|
||||
commands =
|
||||
pytest -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
||||
|
||||
[testenv:py35-pexpect]
|
||||
changedir=testing
|
||||
platform=linux|darwin
|
||||
deps={[testenv:py27-pexpect]deps}
|
||||
commands=
|
||||
pytest -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
||||
changedir = testing
|
||||
platform = linux|darwin
|
||||
deps = {[testenv:py27-pexpect]deps}
|
||||
commands =
|
||||
pytest -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
||||
|
||||
[testenv:py27-nobyte]
|
||||
deps=
|
||||
deps =
|
||||
pytest-xdist>=1.13
|
||||
hypothesis>=3.5.2
|
||||
distribute=true
|
||||
setenv=
|
||||
distribute = true
|
||||
setenv =
|
||||
PYTHONDONTWRITEBYTECODE=1
|
||||
commands=
|
||||
pytest -n3 -rfsxX {posargs:testing}
|
||||
commands =
|
||||
pytest -n3 -rfsxX {posargs:testing}
|
||||
|
||||
[testenv:py27-trial]
|
||||
deps=twisted
|
||||
commands=
|
||||
pytest -ra {posargs:testing/test_unittest.py}
|
||||
deps = twisted
|
||||
commands =
|
||||
pytest -ra {posargs:testing/test_unittest.py}
|
||||
|
||||
[testenv:py35-trial]
|
||||
deps={[testenv:py27-trial]deps}
|
||||
commands=
|
||||
pytest -ra {posargs:testing/test_unittest.py}
|
||||
deps = {[testenv:py27-trial]deps}
|
||||
commands =
|
||||
pytest -ra {posargs:testing/test_unittest.py}
|
||||
|
||||
[testenv:docs]
|
||||
skipsdist=True
|
||||
usedevelop=True
|
||||
basepython=python
|
||||
changedir=doc/en
|
||||
deps=
|
||||
skipsdist = True
|
||||
usedevelop = True
|
||||
basepython = python
|
||||
changedir = doc/en
|
||||
deps =
|
||||
sphinx
|
||||
PyYAML
|
||||
|
||||
commands=
|
||||
commands =
|
||||
sphinx-build -W -b html . _build
|
||||
|
||||
[testenv:doctesting]
|
||||
basepython = python
|
||||
usedevelop=True
|
||||
skipsdist=True
|
||||
usedevelop = True
|
||||
skipsdist = True
|
||||
# ensure the given pyargs cant mean anytrhing else
|
||||
changedir=doc/
|
||||
deps=
|
||||
changedir = doc/
|
||||
deps =
|
||||
PyYAML
|
||||
commands=
|
||||
commands =
|
||||
pytest -rfsxX en
|
||||
pytest --doctest-modules --pyargs _pytest
|
||||
|
||||
[testenv:regen]
|
||||
changedir=doc/en
|
||||
skipsdist=True
|
||||
changedir = doc/en
|
||||
skipsdist = True
|
||||
basepython = python3.5
|
||||
deps=sphinx
|
||||
PyYAML
|
||||
regendoc>=0.6.1
|
||||
whitelist_externals=
|
||||
deps =
|
||||
sphinx
|
||||
PyYAML
|
||||
regendoc>=0.6.1
|
||||
whitelist_externals =
|
||||
rm
|
||||
make
|
||||
commands=
|
||||
commands =
|
||||
rm -rf /tmp/doc-exec*
|
||||
make regen
|
||||
|
||||
[testenv:jython]
|
||||
changedir=testing
|
||||
commands=
|
||||
changedir = testing
|
||||
commands =
|
||||
{envpython} {envbindir}/py.test-jython -rfsxX {posargs}
|
||||
|
||||
[testenv:freeze]
|
||||
changedir=testing/freeze
|
||||
deps=pyinstaller
|
||||
commands=
|
||||
changedir = testing/freeze
|
||||
deps = pyinstaller
|
||||
commands =
|
||||
{envpython} create_executable.py
|
||||
{envpython} tox_run.py
|
||||
|
||||
|
||||
[testenv:coveralls]
|
||||
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
|
||||
usedevelop=True
|
||||
basepython=python3.5
|
||||
changedir=.
|
||||
usedevelop = True
|
||||
basepython = python3.5
|
||||
changedir = .
|
||||
deps =
|
||||
{[testenv]deps}
|
||||
coveralls
|
||||
commands=
|
||||
commands =
|
||||
coverage run --source=_pytest -m pytest testing
|
||||
coverage report -m
|
||||
coveralls
|
||||
|
||||
[pytest]
|
||||
minversion=2.0
|
||||
plugins=pytester
|
||||
minversion = 2.0
|
||||
plugins = pytester
|
||||
#--pyargs --doctest-modules --ignore=.tox
|
||||
addopts= -rxsX -p pytester --ignore=testing/cx_freeze
|
||||
rsyncdirs=tox.ini pytest.py _pytest testing
|
||||
python_files=test_*.py *_test.py testing/*/*.py
|
||||
python_classes=Test Acceptance
|
||||
python_functions=test
|
||||
addopts = -rxsX -p pytester --ignore=testing/cx_freeze
|
||||
rsyncdirs = tox.ini pytest.py _pytest testing
|
||||
python_files = test_*.py *_test.py testing/*/*.py
|
||||
python_classes = Test Acceptance
|
||||
python_functions = test
|
||||
norecursedirs = .tox ja .hg cx_freeze_source
|
||||
filterwarnings=
|
||||
# produced by path.local
|
||||
ignore:bad escape.*:DeprecationWarning:re
|
||||
# produced by path.readlines
|
||||
ignore:.*U.*mode is deprecated:DeprecationWarning
|
||||
# produced by pytest-xdist
|
||||
ignore:.*type argument to addoption.*:DeprecationWarning
|
||||
# produced by python >=3.5 on execnet (pytest-xdist)
|
||||
ignore:.*inspect.getargspec.*deprecated, use inspect.signature.*:DeprecationWarning
|
||||
filterwarnings =
|
||||
# produced by path.local
|
||||
ignore:bad escape.*:DeprecationWarning:re
|
||||
# produced by path.readlines
|
||||
ignore:.*U.*mode is deprecated:DeprecationWarning
|
||||
# produced by pytest-xdist
|
||||
ignore:.*type argument to addoption.*:DeprecationWarning
|
||||
# produced by python >=3.5 on execnet (pytest-xdist)
|
||||
ignore:.*inspect.getargspec.*deprecated, use inspect.signature.*:DeprecationWarning
|
||||
|
||||
[flake8]
|
||||
ignore =E401,E225,E261,E128,E124,E301,E302,E121,E303,W391,E501,E231,E126,E701,E265,E241,E251,E226,E101,W191,E131,E203,E122,E123,E271,E712,E222,E127,E125,E221,W292,E111,E113,E293,E262,W293,E129,E702,E201,E272,E202,E704,E731,E402
|
||||
max-line-length = 120
|
||||
exclude = _pytest/vendored_packages/pluggy.py
|
||||
|
|
Loading…
Reference in New Issue