Merge branch 'fix-flake8-issues'

This commit is contained in:
Bruno Oliveira 2017-07-19 17:03:36 -03:00
commit c92760dca8
80 changed files with 1549 additions and 1082 deletions

View File

@ -9,6 +9,7 @@ Ahn Ki-Wook
Alexander Johnson
Alexei Kozlenok
Anatoly Bubenkoff
Andras Tim
Andreas Zeidler
Andrzej Ostrowski
Andy Freeland

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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,))

View File

@ -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.

View File

@ -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)

View File

@ -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)]

View File

@ -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)

View File

@ -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')

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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 ''

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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):

View File

@ -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)

View File

@ -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]))

View File

@ -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)

View File

@ -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

View File

@ -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:]

View File

@ -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 = []

View File

@ -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

View File

@ -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)

View File

@ -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)

1
changelog/2581.trivial Normal file
View File

@ -0,0 +1 @@
Fixed all flake8 errors and warnings

View File

@ -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")

View File

@ -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]

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -6,4 +6,4 @@ py.test main().
if __name__ == '__main__':
import sys
import pytest
sys.exit(pytest.main())
sys.exit(pytest.main())

View File

@ -2,5 +2,6 @@
def test_upper():
assert 'foo'.upper() == 'FOO'
def test_lower():
assert 'FOO'.lower() == 'foo'
assert 'FOO'.lower() == 'foo'

View File

@ -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))

View File

@ -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 *=',
])

View File

@ -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)

View File

@ -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))

View File

@ -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"

View File

@ -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):

View File

@ -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):

View File

@ -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):

View File

@ -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():

View File

@ -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()

View File

@ -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

View File

@ -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'):

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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*"
])

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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'

View File

@ -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()

View File

@ -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(

View File

@ -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"])

View File

@ -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")

View File

@ -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('''

View File

@ -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

View File

@ -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 == ''

View File

@ -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

View File

@ -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

View File

@ -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("""

View File

@ -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)

View File

@ -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):

View File

@ -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

View File

@ -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
View File

@ -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