Merge remote-tracking branch 'upstream/features' into integrate-pytest-warnings

This commit is contained in:
Bruno Oliveira 2017-03-20 19:59:05 -03:00
commit 9f85584656
77 changed files with 345 additions and 149 deletions

View File

@ -16,6 +16,9 @@ New Features
* ``pytest.raises`` now asserts that the error message matches a text or regex
with the ``match`` keyword argument. Thanks `@Kriechi`_ for the PR.
* ``pytest.param`` can be used to declare test parameter sets with marks and test ids.
Thanks `@RonnyPfannschmidt`_ for the PR.
Changes
-------

View File

@ -206,12 +206,12 @@ but here is a simple overview:
#. Run all the tests
You need to have Python 2.7 and 3.5 available in your system. Now
You need to have Python 2.7 and 3.6 available in your system. Now
running tests is as simple as issuing this command::
$ tox -e linting,py27,py35
$ tox -e linting,py27,py36
This command will run tests via the "tox" tool against Python 2.7 and 3.5
This command will run tests via the "tox" tool against Python 2.7 and 3.6
and also perform "lint" coding-style checks.
#. You can now edit your local working copy.
@ -223,9 +223,9 @@ but here is a simple overview:
$ tox -e py27 -- --pdb
Or to only run tests in a particular test module on Python 3.5::
Or to only run tests in a particular test module on Python 3.6::
$ tox -e py35 -- testing/test_config.py
$ tox -e py36 -- testing/test_config.py
#. Commit and push once your tests pass and you are happy with your change(s)::

View File

@ -57,7 +57,7 @@ If things do not work right away:
which should throw a KeyError: 'COMPLINE' (which is properly set by the
global argcomplete script).
"""
from __future__ import absolute_import, division, print_function
import sys
import os
from glob import glob

View File

@ -1,4 +1,5 @@
""" python inspection/code generation API """
from __future__ import absolute_import, division, print_function
from .code import Code # noqa
from .code import ExceptionInfo # noqa
from .code import Frame # noqa

View File

@ -2,6 +2,7 @@
# CHANGES:
# - some_str is replaced, trying to create unicode strings
#
from __future__ import absolute_import, division, print_function
import types
def format_exception_only(etype, value):

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import sys
from inspect import CO_VARARGS, CO_VARKEYWORDS
import re

View File

@ -1,4 +1,4 @@
from __future__ import generators
from __future__ import absolute_import, division, generators, print_function
from bisect import bisect_right
import sys

View File

@ -2,7 +2,7 @@
imports symbols from vendored "pluggy" if available, otherwise
falls back to importing "pluggy" from the default namespace.
"""
from __future__ import absolute_import, division, print_function
try:
from _pytest.vendored_packages.pluggy import * # noqa
from _pytest.vendored_packages.pluggy import __version__ # noqa

View File

@ -1,6 +1,7 @@
"""
support for presenting detailed information in failing assertions.
"""
from __future__ import absolute_import, division, print_function
import py
import sys

View File

@ -1,5 +1,5 @@
"""Rewrite assertion AST to produce nice error messages"""
from __future__ import absolute_import, division, print_function
import ast
import _ast
import errno

View File

@ -4,7 +4,7 @@ Utilities for truncating assertion output.
Current default behaviour is to truncate assertion explanations at
~8 terminal lines, unless running in "-vv" mode or running on CI.
"""
from __future__ import absolute_import, division, print_function
import os
import py

View File

@ -1,4 +1,5 @@
"""Utilities for assertion debugging"""
from __future__ import absolute_import, division, print_function
import pprint
import _pytest._code

View File

@ -4,7 +4,7 @@ merged implementation of the cache provider
the name cache was not chosen to ensure pluggy automatically
ignores the external pytest-cache
"""
from __future__ import absolute_import, division, print_function
import py
import pytest
import json

View File

@ -2,7 +2,7 @@
per-test stdout/stderr capturing mechanism.
"""
from __future__ import with_statement
from __future__ import absolute_import, division, print_function
import contextlib
import sys

View File

@ -1,6 +1,7 @@
"""
python version compatibility code
"""
from __future__ import absolute_import, division, print_function
import sys
import inspect
import types

View File

@ -1,4 +1,5 @@
""" command line options, ini-file and conftest.py processing. """
from __future__ import absolute_import, division, print_function
import argparse
import shlex
import traceback

View File

@ -1,5 +1,5 @@
""" interactive debugging with PDB, the Python Debugger. """
from __future__ import absolute_import
from __future__ import absolute_import, division, print_function
import pdb
import sys

View File

@ -5,7 +5,7 @@ that is planned to be removed in the next pytest release.
Keeping it in a central location makes it easy to track what is deprecated and should
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.'

View File

@ -1,5 +1,5 @@
""" discover and run doctests in modules and test files."""
from __future__ import absolute_import
from __future__ import absolute_import, division, print_function
import traceback

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import sys
from py._code.code import FormattedExcinfo

View File

@ -2,6 +2,8 @@
Provides a function to report all internal modules for using freezing tools
pytest
"""
from __future__ import absolute_import, division, print_function
def pytest_namespace():
return {'freeze_includes': freeze_includes}
@ -42,4 +44,4 @@ def _iter_all_modules(package, prefix=''):
for m in _iter_all_modules(os.path.join(path, name), prefix=name + '.'):
yield prefix + m
else:
yield prefix + name
yield prefix + name

View File

@ -1,4 +1,6 @@
""" version info, help messages, tracing configuration. """
from __future__ import absolute_import, division, print_function
import py
import pytest
import os, sys

View File

@ -4,9 +4,11 @@
Based on initial code from Ross Lawley.
Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
"""
# Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
# src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
from __future__ import absolute_import, division, print_function
import functools
import py

View File

@ -1,4 +1,6 @@
""" core implementation of testing process: init, session, runtest loop. """
from __future__ import absolute_import, division, print_function
import functools
import os
import sys

View File

@ -1,20 +1,77 @@
""" generic mechanism for marking and selecting python functions. """
from __future__ import absolute_import, division, print_function
import inspect
from collections import namedtuple
from operator import attrgetter
from .compat import imap
def alias(name):
return property(attrgetter(name), doc='alias for ' + name)
class ParameterSet(namedtuple('ParameterSet', 'values, marks, id')):
@classmethod
def param(cls, *values, **kw):
marks = kw.pop('marks', ())
if isinstance(marks, MarkDecorator):
marks = marks,
else:
assert isinstance(marks, (tuple, list, set))
def param_extract_id(id=None):
return id
id = param_extract_id(**kw)
return cls(values, marks, id)
@classmethod
def extract_from(cls, parameterset, legacy_force_tuple=False):
"""
:param parameterset:
a legacy style parameterset that may or may not be a tuple,
and may or may not be wrapped into a mess of mark objects
:param legacy_force_tuple:
enforce tuple wrapping so single argument tuple values
don't get decomposed and break tests
"""
if isinstance(parameterset, cls):
return parameterset
if not isinstance(parameterset, MarkDecorator) and legacy_force_tuple:
return cls.param(parameterset)
newmarks = []
argval = parameterset
while isinstance(argval, MarkDecorator):
newmarks.append(MarkDecorator(Mark(
argval.markname, argval.args[:-1], argval.kwargs)))
argval = argval.args[-1]
assert not isinstance(argval, ParameterSet)
if legacy_force_tuple:
argval = argval,
return cls(argval, marks=newmarks, id=None)
@property
def deprecated_arg_dict(self):
return dict((mark.name, mark) for mark in self.marks)
class MarkerError(Exception):
"""Error in use of a pytest marker/attribute."""
def pytest_namespace():
return {'mark': MarkGenerator()}
return {
'mark': MarkGenerator(),
'param': ParameterSet.param,
}
def pytest_addoption(parser):
@ -210,6 +267,7 @@ def istestfunc(func):
return hasattr(func, "__call__") and \
getattr(func, "__name__", "<lambda>") != "<lambda>"
class MarkDecorator(object):
""" A decorator for test functions and test classes. When applied
it will create :class:`MarkInfo` objects which may be
@ -255,8 +313,11 @@ class MarkDecorator(object):
def markname(self):
return self.name # for backward-compat (2.4.1 had this attr)
def __eq__(self, other):
return self.mark == other.mark
def __repr__(self):
return "<MarkDecorator %r>" % self.mark
return "<MarkDecorator %r>" % (self.mark,)
def __call__(self, *args, **kwargs):
""" if passed a single callable argument: decorate it with mark info.
@ -289,19 +350,7 @@ class MarkDecorator(object):
return self.__class__(self.mark.combined_with(mark))
def extract_argvalue(maybe_marked_args):
# TODO: incorrect mark data, the old code wanst able to collect lists
# individual parametrized argument sets can be wrapped in a series
# of markers in which case we unwrap the values and apply the mark
# at Function init
newmarks = {}
argval = maybe_marked_args
while isinstance(argval, MarkDecorator):
newmark = MarkDecorator(Mark(
argval.markname, argval.args[:-1], argval.kwargs))
newmarks[newmark.name] = newmark
argval = argval.args[-1]
return argval, newmarks
class Mark(namedtuple('Mark', 'name, args, kwargs')):

View File

@ -1,4 +1,5 @@
""" monkeypatching and mocking functionality. """
from __future__ import absolute_import, division, print_function
import os, sys
import re

View File

@ -1,4 +1,5 @@
""" run test suites written for nose. """
from __future__ import absolute_import, division, print_function
import sys

View File

@ -1,4 +1,6 @@
""" submit failure or test session information to a pastebin service. """
from __future__ import absolute_import, division, print_function
import pytest
import sys
import tempfile

View File

@ -1,4 +1,6 @@
""" (disabled by default) support for testing pytest and pytest plugins. """
from __future__ import absolute_import, division, print_function
import codecs
import gc
import os
@ -12,8 +14,6 @@ from fnmatch import fnmatch
from weakref import WeakKeyDictionary
from py.builtin import print_
from _pytest.capture import MultiCapture, SysCapture
from _pytest._code import Source
import py
@ -229,15 +229,15 @@ class HookRecorder(object):
name, check = entries.pop(0)
for ind, call in enumerate(self.calls[i:]):
if call._name == name:
print_("NAMEMATCH", name, call)
print("NAMEMATCH", name, call)
if eval(check, backlocals, call.__dict__):
print_("CHECKERMATCH", repr(check), "->", call)
print("CHECKERMATCH", repr(check), "->", call)
else:
print_("NOCHECKERMATCH", repr(check), "-", call)
print("NOCHECKERMATCH", repr(check), "-", call)
continue
i += ind + 1
break
print_("NONAMEMATCH", name, "with", call)
print("NONAMEMATCH", name, "with", call)
else:
pytest.fail("could not find %r check %r" % (name, check))
@ -924,8 +924,8 @@ class Testdir(object):
cmdargs = [str(x) for x in cmdargs]
p1 = self.tmpdir.join("stdout")
p2 = self.tmpdir.join("stderr")
print_("running:", ' '.join(cmdargs))
print_(" in:", str(py.path.local()))
print("running:", ' '.join(cmdargs))
print(" in:", str(py.path.local()))
f1 = codecs.open(str(p1), "w", encoding="utf8")
f2 = codecs.open(str(p2), "w", encoding="utf8")
try:
@ -951,7 +951,7 @@ class Testdir(object):
def _dump_lines(self, lines, fp):
try:
for line in lines:
py.builtin.print_(line, file=fp)
print(line, file=fp)
except UnicodeEncodeError:
print("couldn't print to %s because of encoding" % (fp,))

View File

@ -1,4 +1,5 @@
""" Python test discovery, setup and run of test functions. """
from __future__ import absolute_import, division, print_function
import fnmatch
import inspect
@ -787,36 +788,35 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
to set a dynamic scope using test context or configuration.
"""
from _pytest.fixtures import scope2index
from _pytest.mark import extract_argvalue
from _pytest.mark import ParameterSet
from py.io import saferepr
unwrapped_argvalues = []
newkeywords = []
for maybe_marked_args in argvalues:
argval, newmarks = extract_argvalue(maybe_marked_args)
unwrapped_argvalues.append(argval)
newkeywords.append(newmarks)
argvalues = unwrapped_argvalues
if not isinstance(argnames, (tuple, list)):
argnames = [x.strip() for x in argnames.split(",") if x.strip()]
if len(argnames) == 1:
argvalues = [(val,) for val in argvalues]
if not argvalues:
argvalues = [(NOTSET,) * len(argnames)]
# we passed a empty list to parameterize, skip that test
#
force_tuple = len(argnames) == 1
else:
force_tuple = False
parameters = [
ParameterSet.extract_from(x, legacy_force_tuple=force_tuple)
for x in argvalues]
del argvalues
if not parameters:
fs, lineno = getfslineno(self.function)
newmark = pytest.mark.skip(
reason="got empty parameter set %r, function %s at %s:%d" % (
argnames, self.function.__name__, fs, lineno))
newkeywords = [{newmark.markname: newmark}]
reason = "got empty parameter set %r, function %s at %s:%d" % (
argnames, self.function.__name__, fs, lineno)
mark = pytest.mark.skip(reason=reason)
parameters.append(ParameterSet(
values=(NOTSET,) * len(argnames),
marks=[mark],
id=None,
))
if scope is None:
scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
scopenum = scope2index(
scope, descr='call to {0}'.format(self.parametrize))
scopenum = scope2index(scope, descr='call to {0}'.format(self.parametrize))
valtypes = {}
for arg in argnames:
if arg not in self.fixturenames:
@ -844,22 +844,22 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
idfn = ids
ids = None
if ids:
if len(ids) != len(argvalues):
raise ValueError('%d tests specified with %d ids' %(
len(argvalues), len(ids)))
if len(ids) != len(parameters):
raise ValueError('%d tests specified with %d ids' % (
len(parameters), len(ids)))
for id_value in ids:
if id_value is not None and not isinstance(id_value, py.builtin._basestring):
msg = 'ids must be list of strings, found: %s (type: %s)'
raise ValueError(msg % (saferepr(id_value), type(id_value).__name__))
ids = idmaker(argnames, argvalues, idfn, ids, self.config)
ids = idmaker(argnames, parameters, idfn, ids, self.config)
newcalls = []
for callspec in self._calls or [CallSpec2(self)]:
elements = zip(ids, argvalues, newkeywords, count())
for a_id, valset, keywords, param_index in elements:
assert len(valset) == len(argnames)
elements = zip(ids, parameters, count())
for a_id, param, param_index in elements:
assert len(param.values) == len(argnames)
newcallspec = callspec.copy(self)
newcallspec.setmulti(valtypes, argnames, valset, a_id,
keywords, scopenum, param_index)
newcallspec.setmulti(valtypes, argnames, param.values, a_id,
param.deprecated_arg_dict, scopenum, param_index)
newcalls.append(newcallspec)
self._calls = newcalls
@ -958,17 +958,19 @@ def _idval(val, argname, idx, idfn, config=None):
return val.__name__
return str(argname)+str(idx)
def _idvalset(idx, valset, argnames, idfn, ids, config=None):
def _idvalset(idx, parameterset, argnames, idfn, ids, config=None):
if parameterset.id is not None:
return parameterset.id
if ids is None or (idx >= len(ids) or ids[idx] is None):
this_id = [_idval(val, argname, idx, idfn, config)
for val, argname in zip(valset, argnames)]
for val, argname in zip(parameterset.values, argnames)]
return "-".join(this_id)
else:
return _escape_strings(ids[idx])
def idmaker(argnames, argvalues, idfn=None, ids=None, config=None):
ids = [_idvalset(valindex, valset, argnames, idfn, ids, config)
for valindex, valset in enumerate(argvalues)]
def idmaker(argnames, parametersets, idfn=None, ids=None, config=None):
ids = [_idvalset(valindex, parameterset, argnames, idfn, ids, config)
for valindex, parameterset in enumerate(parametersets)]
if len(set(ids)) != len(ids):
# The ids are not unique
duplicates = [testid for testid in ids if ids.count(testid) > 1]

View File

@ -1,4 +1,6 @@
""" recording warnings during test function execution. """
from __future__ import absolute_import, division, print_function
import inspect
import _pytest._code

View File

@ -1,6 +1,7 @@
""" log machine-parseable test session result information in a plain
text file.
"""
from __future__ import absolute_import, division, print_function
import py
import os
@ -61,9 +62,9 @@ class ResultLog(object):
self.logfile = logfile # preferably line buffered
def write_log_entry(self, testpath, lettercode, longrepr):
py.builtin.print_("%s %s" % (lettercode, testpath), file=self.logfile)
print("%s %s" % (lettercode, testpath), file=self.logfile)
for line in longrepr.splitlines():
py.builtin.print_(" %s" % line, file=self.logfile)
print(" %s" % line, file=self.logfile)
def log_outcome(self, report, lettercode, longrepr):
testpath = getattr(report, 'nodeid', None)

View File

@ -1,4 +1,6 @@
""" basic collect and runtest protocol implementations """
from __future__ import absolute_import, division, print_function
import bdb
import sys
from time import time

View File

@ -1,3 +1,5 @@
from __future__ import absolute_import, division, print_function
import pytest
import sys

View File

@ -1,3 +1,5 @@
from __future__ import absolute_import, division, print_function
import pytest

View File

@ -1,4 +1,6 @@
""" support for skip/xfail functions and markers. """
from __future__ import absolute_import, division, print_function
import os
import sys
import traceback

View File

@ -2,8 +2,9 @@
This is a good source for looking at the various reporting hooks.
"""
import itertools
from __future__ import absolute_import, division, print_function
import itertools
from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \
EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED
import pytest

View File

@ -1,4 +1,6 @@
""" support for providing temporary directories to test functions. """
from __future__ import absolute_import, division, print_function
import re
import pytest

View File

@ -1,5 +1,5 @@
""" discovery and running of std-library "unittest" style tests. """
from __future__ import absolute_import
from __future__ import absolute_import, division, print_function
import sys
import traceback

View File

@ -55,17 +55,17 @@ them in turn::
$ pytest
======= test session starts ========
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 3 items
test_expectation.py ..F
======= FAILURES ========
_______ test_eval[6*9-42] ________
test_input = '6*9', expected = 42
@pytest.mark.parametrize("test_input,expected", [
("3+5", 8),
("2+4", 6),
@ -73,9 +73,9 @@ them in turn::
])
def test_eval(test_input, expected):
> assert eval(test_input) == expected
E AssertionError: assert 54 == 42
E assert 54 == 42
E + where 54 = eval('6*9')
test_expectation.py:8: AssertionError
======= 1 failed, 2 passed in 0.12 seconds ========
@ -94,21 +94,42 @@ for example with the builtin ``mark.xfail``::
@pytest.mark.parametrize("test_input,expected", [
("3+5", 8),
("2+4", 6),
pytest.mark.xfail(("6*9", 42)),
pytest.param("6*9", 42,
marks=pytest.mark.xfail),
])
def test_eval(test_input, expected):
assert eval(test_input) == expected
.. note::
prior to version 3.1 the supported mechanism for marking values
used the syntax::
import pytest
@pytest.mark.parametrize("test_input,expected", [
("3+5", 8),
("2+4", 6),
pytest.mark.xfail(("6*9", 42),),
])
def test_eval(test_input, expected):
assert eval(test_input) == expected
This was an initial hack to support the feature but soon was demonstrated to be incomplete,
broken for passing functions or applying multiple marks with the same name but different parameters.
The old syntax will be removed in pytest-4.0.
Let's run this::
$ pytest
======= test session starts ========
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
platform linux -- Python 3.5.2, pytest-3.0.3, py-1.4.31, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 3 items
test_expectation.py ..x
======= 2 passed, 1 xfailed in 0.12 seconds ========
The one parameter set which caused a failure previously now
@ -181,15 +202,15 @@ Let's also run with a stringinput that will lead to a failing test::
F
======= FAILURES ========
_______ test_valid_string[!] ________
stringinput = '!'
def test_valid_string(stringinput):
> assert stringinput.isalpha()
E AssertionError: assert False
E assert False
E + where False = <built-in method isalpha of str object at 0xdeadbeef>()
E + where <built-in method isalpha of str object at 0xdeadbeef> = '!'.isalpha
test_strings.py:3: AssertionError
1 failed in 0.12 seconds

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
import os
import sys

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import sys
import _pytest._code

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
import operator
import _pytest
@ -369,7 +370,7 @@ def test_codepath_Queue_example():
def test_match_succeeds():
with pytest.raises(ZeroDivisionError) as excinfo:
0 / 0
0 // 0
excinfo.match(r'.*zero.*')
def test_match_raises_error(testdir):

View File

@ -1,6 +1,7 @@
# flake8: noqa
# disable flake check on this file because some constructs are strange
# or redundant on purpose and can't be disable on a line-by-line basis
from __future__ import absolute_import, division, print_function
import sys
import _pytest._code

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import pytest

View File

@ -274,6 +274,7 @@ class TestGenerator(object):
def test_order_of_execution_generator_same_codeline(self, testdir, tmpdir):
o = testdir.makepyfile("""
from __future__ import print_function
def test_generative_order_of_execution():
import py, pytest
test_list = []
@ -283,8 +284,8 @@ class TestGenerator(object):
test_list.append(item)
def assert_order_of_execution():
py.builtin.print_('expected order', expected_list)
py.builtin.print_('but got ', test_list)
print('expected order', expected_list)
print('but got ', test_list)
assert test_list == expected_list
for i in expected_list:
@ -298,6 +299,7 @@ class TestGenerator(object):
def test_order_of_execution_generator_different_codeline(self, testdir):
o = testdir.makepyfile("""
from __future__ import print_function
def test_generative_tests_different_codeline():
import py, pytest
test_list = []
@ -313,8 +315,8 @@ class TestGenerator(object):
test_list.append(0)
def assert_order_of_execution():
py.builtin.print_('expected order', expected_list)
py.builtin.print_('but got ', test_list)
print('expected order', expected_list)
print('but got ', test_list)
assert test_list == expected_list
yield list_append_0

View File

@ -207,37 +207,40 @@ class TestMetafunc(object):
@pytest.mark.issue250
def test_idmaker_autoname(self):
from _pytest.python import idmaker
result = idmaker(("a", "b"), [("string", 1.0),
("st-ring", 2.0)])
result = idmaker(("a", "b"), [pytest.param("string", 1.0),
pytest.param("st-ring", 2.0)])
assert result == ["string-1.0", "st-ring-2.0"]
result = idmaker(("a", "b"), [(object(), 1.0),
(object(), object())])
result = idmaker(("a", "b"), [pytest.param(object(), 1.0),
pytest.param(object(), object())])
assert result == ["a0-1.0", "a1-b1"]
# unicode mixing, issue250
result = idmaker((py.builtin._totext("a"), "b"), [({}, b'\xc3\xb4')])
result = idmaker(
(py.builtin._totext("a"), "b"),
[pytest.param({}, b'\xc3\xb4')])
assert result == ['a0-\\xc3\\xb4']
def test_idmaker_with_bytes_regex(self):
from _pytest.python import idmaker
result = idmaker(("a"), [(re.compile(b'foo'), 1.0)])
result = idmaker(("a"), [pytest.param(re.compile(b'foo'), 1.0)])
assert result == ["foo"]
def test_idmaker_native_strings(self):
from _pytest.python import idmaker
totext = py.builtin._totext
result = idmaker(("a", "b"), [(1.0, -1.1),
(2, -202),
("three", "three hundred"),
(True, False),
(None, None),
(re.compile('foo'), re.compile('bar')),
(str, int),
(list("six"), [66, 66]),
(set([7]), set("seven")),
(tuple("eight"), (8, -8, 8)),
(b'\xc3\xb4', b"name"),
(b'\xc3\xb4', totext("other")),
result = idmaker(("a", "b"), [
pytest.param(1.0, -1.1),
pytest.param(2, -202),
pytest.param("three", "three hundred"),
pytest.param(True, False),
pytest.param(None, None),
pytest.param(re.compile('foo'), re.compile('bar')),
pytest.param(str, int),
pytest.param(list("six"), [66, 66]),
pytest.param(set([7]), set("seven")),
pytest.param(tuple("eight"), (8, -8, 8)),
pytest.param(b'\xc3\xb4', b"name"),
pytest.param(b'\xc3\xb4', totext("other")),
])
assert result == ["1.0--1.1",
"2--202",
@ -257,7 +260,7 @@ class TestMetafunc(object):
from _pytest.python import idmaker
enum = pytest.importorskip("enum")
e = enum.Enum("Foo", "one, two")
result = idmaker(("a", "b"), [(e.one, e.two)])
result = idmaker(("a", "b"), [pytest.param(e.one, e.two)])
assert result == ["Foo.one-Foo.two"]
@pytest.mark.issue351
@ -268,9 +271,10 @@ class TestMetafunc(object):
if isinstance(val, Exception):
return repr(val)
result = idmaker(("a", "b"), [(10.0, IndexError()),
(20, KeyError()),
("three", [1, 2, 3]),
result = idmaker(("a", "b"), [
pytest.param(10.0, IndexError()),
pytest.param(20, KeyError()),
pytest.param("three", [1, 2, 3]),
], idfn=ids)
assert result == ["10.0-IndexError()",
"20-KeyError()",
@ -284,9 +288,9 @@ class TestMetafunc(object):
def ids(val):
return 'a'
result = idmaker(("a", "b"), [(10.0, IndexError()),
(20, KeyError()),
("three", [1, 2, 3]),
result = idmaker(("a", "b"), [pytest.param(10.0, IndexError()),
pytest.param(20, KeyError()),
pytest.param("three", [1, 2, 3]),
], idfn=ids)
assert result == ["a-a0",
"a-a1",
@ -306,9 +310,10 @@ class TestMetafunc(object):
rec = WarningsRecorder()
with rec:
idmaker(("a", "b"), [(10.0, IndexError()),
(20, KeyError()),
("three", [1, 2, 3]),
idmaker(("a", "b"), [
pytest.param(10.0, IndexError()),
pytest.param(20, KeyError()),
pytest.param("three", [1, 2, 3]),
], idfn=ids)
assert [str(i.message) for i in rec.list] == [
@ -351,14 +356,21 @@ class TestMetafunc(object):
def test_idmaker_with_ids(self):
from _pytest.python import idmaker
result = idmaker(("a", "b"), [(1, 2),
(3, 4)],
result = idmaker(("a", "b"), [pytest.param(1, 2),
pytest.param(3, 4)],
ids=["a", None])
assert result == ["a", "3-4"]
def test_idmaker_with_paramset_id(self):
from _pytest.python import idmaker
result = idmaker(("a", "b"), [pytest.param(1, 2, id="me"),
pytest.param(3, 4, id="you")],
ids=["a", None])
assert result == ["me", "you"]
def test_idmaker_with_ids_unique_names(self):
from _pytest.python import idmaker
result = idmaker(("a"), [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"]
@ -1438,6 +1450,31 @@ 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 = """
import pytest
@pytest.mark.parametrize(("n", "expected"), [
pytest.param(
2,3,
marks=pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict}),
),
pytest.param(
2,3,
marks=[pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict})],
),
])
def test_increment(n, expected):
assert n + 1 == expected
""".format(strict=strict)
testdir.makepyfile(s)
reprec = testdir.inline_run()
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

@ -1,4 +1,4 @@
from __future__ import with_statement
from __future__ import absolute_import, division, print_function
import py, pytest
# test for _argcomplete but not specific for any application

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
import sys
import textwrap

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import glob
import os
import py_compile

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import sys
import _pytest

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
# note: py.io capture tests where copied from
# pylib 1.4.20.dev2 (rev 13d9af95547e)
from __future__ import with_statement
@ -13,7 +14,7 @@ import contextlib
from _pytest import capture
from _pytest.capture import CaptureManager
from _pytest.main import EXIT_NOTESTSCOLLECTED
from py.builtin import print_
needsosdup = pytest.mark.xfail("not hasattr(os, 'dup')")
@ -711,7 +712,7 @@ def test_dupfile(tmpfile):
assert nf != tmpfile
assert nf.fileno() != tmpfile.fileno()
assert nf not in flist
print_(i, end="", file=nf)
print(i, end="", file=nf)
flist.append(nf)
for i in range(5):
f = flist[i]
@ -785,7 +786,7 @@ class TestFDCapture(object):
def test_stderr(self):
cap = capture.FDCapture(2)
cap.start()
print_("hello", file=sys.stderr)
print("hello", file=sys.stderr)
s = cap.snap()
cap.done()
assert s == "hello\n"

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import pytest, py
from _pytest.main import Session, EXIT_NOTESTSCOLLECTED

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import sys
import pytest

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import py, pytest
import _pytest._code

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
from textwrap import dedent
import _pytest._code

View File

@ -1,4 +1,5 @@
# encoding: utf-8
from __future__ import absolute_import, division, print_function
import sys
import _pytest._code
from _pytest.compat import MODULE_NOT_FOUND_ERROR

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import pkg_resources
import pytest

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
from _pytest.main import EXIT_NOTESTSCOLLECTED
import pytest

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
from xml.dom import minidom
import py
import sys

View File

@ -1,7 +1,9 @@
from __future__ import absolute_import, division, print_function
import os
import sys
import py, pytest
from _pytest.mark import MarkGenerator as Mark
import pytest
from _pytest.mark import MarkGenerator as Mark, ParameterSet
class TestMark(object):
def test_markinfo_repr(self):
@ -9,9 +11,11 @@ class TestMark(object):
m = MarkInfo(Mark("hello", (1,2), {}))
repr(m)
def test_pytest_exists_in_namespace_all(self):
assert 'mark' in py.test.__all__
assert 'mark' in pytest.__all__
@pytest.mark.parametrize('attr', ['mark', 'param'])
@pytest.mark.parametrize('modulename', ['py.test', 'pytest'])
def test_pytest_exists_in_namespace_all(self, attr, modulename):
module = sys.modules[modulename]
assert attr in module.__all__
def test_pytest_mark_notcallable(self):
mark = Mark()
@ -414,7 +418,7 @@ class TestFunctional(object):
""")
items, rec = testdir.inline_genitems(p)
for item in items:
print (item, item.keywords)
print(item, item.keywords)
assert 'a' in item.keywords
def test_mark_decorator_subclass_does_not_propagate_to_base(self, testdir):
@ -673,7 +677,7 @@ class TestKeywordSelection(object):
item.extra_keyword_matches.add("xxx")
""")
reprec = testdir.inline_run(p.dirpath(), '-s', '-k', keyword)
py.builtin.print_("keyword", repr(keyword))
print("keyword", repr(keyword))
passed, skipped, failed = reprec.listoutcomes()
assert len(passed) == 1
assert passed[0].nodeid.endswith("test_2")
@ -738,3 +742,16 @@ class TestKeywordSelection(object):
assert_test_is_not_selected("__")
assert_test_is_not_selected("()")
@pytest.mark.parametrize('argval, expected', [
(pytest.mark.skip()((1, 2)),
ParameterSet(values=(1, 2), marks=[pytest.mark.skip], id=None)),
(pytest.mark.xfail(pytest.mark.skip()((1, 2))),
ParameterSet(values=(1, 2),
marks=[pytest.mark.xfail, pytest.mark.skip], id=None)),
])
def test_parameterset_extractfrom(argval, expected):
extracted = ParameterSet.extract_from(argval)
assert extracted == expected

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import os
import sys
import textwrap

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import pytest
def setup_module(mod):

View File

@ -1,4 +1,4 @@
from __future__ import with_statement
from __future__ import absolute_import, division, print_function
import sys
import os
import py, pytest

View File

@ -1,4 +1,5 @@
# encoding: utf-8
from __future__ import absolute_import, division, print_function
import sys
import pytest

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import sys
import platform

View File

@ -1,4 +1,5 @@
# encoding: UTF-8
from __future__ import absolute_import, division, print_function
import pytest
import py
import os

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import pytest
import os
from _pytest.pytester import HookRecorder

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import warnings
import re
import py

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import os
import _pytest._code

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from __future__ import absolute_import, division, print_function
import _pytest._code
import os

View File

@ -1,6 +1,8 @@
#
# test correct setup/teardowns at
# module, class, and instance level
"""
test correct setup/teardowns at
module, class, and instance level
"""
from __future__ import absolute_import, division, print_function
import pytest

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import pytest
from _pytest.main import EXIT_NOTESTSCOLLECTED

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import pytest
import sys

View File

@ -1,6 +1,7 @@
"""
terminal reporting of the full testing process.
"""
from __future__ import absolute_import, division, print_function
import collections
import sys

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
import sys
import py
import pytest

View File

@ -1,3 +1,4 @@
from __future__ import absolute_import, division, print_function
from _pytest.main import EXIT_NOTESTSCOLLECTED
import pytest
import gc