From issues-reply at bitbucket.org Sun Feb 1 20:46:46 2015 From: issues-reply at bitbucket.org (taleinat) Date: Sun, 01 Feb 2015 19:46:46 -0000 Subject: [Pytest-commit] Issue #212: escaping curly braces in a tox command doesn't work (hpk42/tox) Message-ID: <20150201194646.25373.65631@app08.ash-private.bitbucket.org> New issue 212: escaping curly braces in a tox command doesn't work https://bitbucket.org/hpk42/tox/issue/212/escaping-curly-braces-in-a-tox-command taleinat: I was trying to delete a few specific files using the "find" command, but couldn't get tox to ignore the required curly braces in the command: ``` py26 runtests: commands[2] | find /Users/.../dev/.../.tox/py26 -name *.so -exec rm \{\} + WARNING:test command found but not installed in testenv cmd: /usr/bin/find env: /Users/.../dev/.../.tox/py26 Maybe forgot to specify a dependency? find: -exec: no terminating ";" or "+" ERROR: InvocationError: '/usr/bin/find /Users/.../dev/.../.tox/py26 -name *.so -exec rm \\{\\} +' ``` My environment: * OSX 10.8 * Python 3.4.2 (installed via pyenv) * tox 1.8.1 (installed via pip) From issues-reply at bitbucket.org Mon Feb 2 20:52:53 2015 From: issues-reply at bitbucket.org (Barry Warsaw) Date: Mon, 02 Feb 2015 19:52:53 -0000 Subject: [Pytest-commit] Issue #213: multi-line factor specification in generated environments are not supported (hpk42/tox) Message-ID: <20150202195253.320.20543@app09.ash-private.bitbucket.org> New issue 213: multi-line factor specification in generated environments are not supported https://bitbucket.org/hpk42/tox/issue/213/multi-line-factor-specification-in Barry Warsaw: I had something like the following in my tox.ini: ``` #! [tox] envlist = {py34,coverage}-{udm,curl} recreate = True [testenv] commands = py34: python -m nose2 -v coverage: python /usr/bin/python3-coverage run {[coverage]rc} -m nose2 -v python3-coverage combine {[coverage]rc} python3-coverage html {[coverage]rc} {[coverage]dir} ``` But `tox -e py34-curl` ended up running all four commands. I thought the coverage: commands would only be run for coverage-* envs but factor specifications cannot span multiple lines. Changing this to: ``` #! [testenv] commands = py34: python -m nose2 -v coverage: python /usr/bin/python3-coverage run {[coverage]rc} -m nose2 -v coverage: python3-coverage combine {[coverage]rc} coverage: python3-coverage html {[coverage]rc} {[coverage]dir} ``` seemed to do the trick. Maybe this is just a documentation issue. From issues-reply at bitbucket.org Mon Feb 2 21:13:59 2015 From: issues-reply at bitbucket.org (Trevor Bekolay) Date: Mon, 02 Feb 2015 20:13:59 -0000 Subject: [Pytest-commit] Issue #672: Make importorskip work with PEP440 compatible versions (hpk42/pytest) Message-ID: <20150202201359.28979.56909@app09.ash-private.bitbucket.org> New issue 672: Make importorskip work with PEP440 compatible versions https://bitbucket.org/hpk42/pytest/issue/672/make-importorskip-work-with-pep440 Trevor Bekolay: Right now, the docstring for `importorskip` notes that only simple versions (e.g. `1.2.3`, but not `2.3-dev`) can be parsed. A package for parsing PEP440-compatible versions exists in the [`packaging`](https://packaging.pypa.io/en/latest/version/) library. I'd be happy to prepare a PR to introduce a dependency on `packaging`, and use it to do version parsing/ordering in `importorskip` (and possibly other places?) but I wanted to check and make sure you'd be comfortable with adding such a dependency. I could alternatively add it in vendorized form (i.e., copying it into the `pytest` source tree directly). Shall I move forward with such a PR? From issues-reply at bitbucket.org Thu Feb 5 22:52:50 2015 From: issues-reply at bitbucket.org (inklesspen) Date: Thu, 05 Feb 2015 21:52:50 -0000 Subject: [Pytest-commit] Issue #673: wrong conftest's fixtures being used? (hpk42/pytest) Message-ID: <20150205215250.17970.15976@app06.ash-private.bitbucket.org> New issue 673: wrong conftest's fixtures being used? https://bitbucket.org/hpk42/pytest/issue/673/wrong-conftests-fixtures-being-used inklesspen: I've got a fun issue that I believe goes back to sys.path and importable packages, but basically: I have two libraries in the same repo. each library has its own test directory, with a conftest.py. Each conftest provides some fixtures with the same name; that is, libA's conftest.py and libB's conftest.py both provide a pyramid_app fixture. This worked fine for a while until libB's test directory got an __init__.py and became a package. Now, libA is getting libB's fixtures instead of its own. That is, libA's test asks for a fixture provided by libA's conftest.py, but it's getting the fixture of the same name from libB's conftest.py Is this something that _should_ work, barring pythonpath issues? or are fixtures supposed to be uniquely named? If it's supposed to work, then I've got a smallish test case that reproduces my problem. From issues-reply at bitbucket.org Fri Feb 6 14:24:39 2015 From: issues-reply at bitbucket.org (Ionel Maries Cristian) Date: Fri, 06 Feb 2015 13:24:39 -0000 Subject: [Pytest-commit] Issue #674: Fixtures from methods wrongly get rebound to request.instance (hpk42/pytest) Message-ID: <20150206132439.30396.45919@app03.ash-private.bitbucket.org> New issue 674: Fixtures from methods wrongly get rebound to request.instance https://bitbucket.org/hpk42/pytest/issue/674/fixtures-from-methods-wrongly-get-rebound Ionel Maries Cristian: In `python.py` there's code like this ``` if self.unittest: result = self.func(request.instance, **kwargs) else: fixturefunc = self.func # the fixture function needs to be bound to the actual # request.instance so that code working with "self" behaves # as expected. if request.instance is not None: fixturefunc = getimfunc(self.func) if fixturefunc != self.func: fixturefunc = fixturefunc.__get__(request.instance) try: result = call_fixture_func(fixturefunc, request, kwargs, self.yieldctx) except Exception: self.cached_result = (None, my_cache_key, sys.exc_info()) raise self.cached_result = (result, my_cache_key, None) ``` If you create a fixture from a plugin like this: https://github.com/ionelmc/pytest-benchmark/blob/9f2c62affb62d580f115d72f99cb662306bfa1d2/src/pytest_benchmark/plugin.py#L294 then you're going to have the request.instance as self. From issues-reply at bitbucket.org Fri Feb 6 16:38:36 2015 From: issues-reply at bitbucket.org (thiefmaster) Date: Fri, 06 Feb 2015 15:38:36 -0000 Subject: [Pytest-commit] Issue #214: How can I install git dependencies even though a package installs an older version? (hpk42/tox) Message-ID: <20150206153836.28796.47880@app10.ash-private.bitbucket.org> New issue 214: How can I install git dependencies even though a package installs an older version? https://bitbucket.org/hpk42/tox/issue/214/how-can-i-install-git-dependencies-even thiefmaster: Right now I'm using this terrible tox.ini: ``` [tox] envlist = {py27,py33,py34}-{release,devel} [testenv] deps = pytest pytest-cov release: flask release: jinja2 commands = devel: pip uninstall -y flask devel: pip install git+git://github.com/mitsuhiko/flask.git devel: pip uninstall -y jinja2 devel: pip install git+git://github.com/mitsuhiko/jinja2.git py.test ``` However, I'd expect it to work with this config: ``` [tox] envlist = {py27,py33,py34}-{release,devel} [testenv] deps = pytest pytest-cov release: jinja2 release: flask devel: git+git://github.com/mitsuhiko/jinja2.git devel: git+git://github.com/mitsuhiko/flask.git commands = py.test ``` My package's setup.py contains `'Flask>=0.7'` in `install_requires` and Flask requires `Jinja2>=2.4`. However, with the second tox.ini I always end up with the latest released Jinja2 from PyPi instead of the dev version from git. From issues-reply at bitbucket.org Sat Feb 7 11:57:44 2015 From: issues-reply at bitbucket.org (David MacIver) Date: Sat, 07 Feb 2015 10:57:44 -0000 Subject: [Pytest-commit] Issue #675: Provide a way for pytester to run coverage on plugins (hpk42/pytest) Message-ID: <20150207105744.22641.64507@app08.ash-private.bitbucket.org> New issue 675: Provide a way for pytester to run coverage on plugins https://bitbucket.org/hpk42/pytest/issue/675/provide-a-way-for-pytester-to-run-coverage David MacIver: Scenario: I am writing a pytest plugin. I want to get coverage information on my plugin's execution. Unfortunately right now this is hard. The problem is that because the plugin is run in a subprocess, it's not actually included in the coverage run, so all the code in my plugin reports as uncovered even if it's actually run. To fix this right now I have to go through a bit of a song and dance to get coverage to automatically execute on all python subprocesses using a sitecustomize file or a .pth file, neither of which are ideal (they're quite hard to set up in my CI environment). It would be really helpful if I could configure pytester with a hook to execute before loading python so that coverage would be provided for the subprocesses as well. From issues-reply at bitbucket.org Sat Feb 7 23:13:57 2015 From: issues-reply at bitbucket.org (Brianna Laugher) Date: Sat, 07 Feb 2015 22:13:57 -0000 Subject: [Pytest-commit] Issue #676: "Adopt pytest month" 2015 (hpk42/pytest) Message-ID: <20150207221357.7403.40986@app02.ash-private.bitbucket.org> New issue 676: "Adopt pytest month" 2015 https://bitbucket.org/hpk42/pytest/issue/676/adopt-pytest-month-2015 Brianna Laugher: As [mentioned](https://mail.python.org/pipermail/pytest-dev/2015-February/002763.html) on the mailing list, it could be useful to have a small project to offer help to open source projects, to encourage them to adopt pytest. It would also be a good way for us to discover "pain points" for new pytest users, for example which areas need better documentation or examples, and maybe even come up with advice about converting existing test suites to pytest. This issue is to collect work related to this effort. Initial plan: * February: gather pytest volunteers * March: advertise and ask for projects interested in taking part * April: the actual work * May: survey/write up how it went Things to do: * Make a short form to gather details about pytest volunteers (e.g. areas of experience/interest) * Make a page to put on the pytest website, with info to advertise to potential projects * Make a short form for projects to apply/register to take part * Pair volunteers and projects together * Survey volunteers and projects after the month is over, write a summary of responses Responsible: pfctdayelise From issues-reply at bitbucket.org Sun Feb 8 13:14:28 2015 From: issues-reply at bitbucket.org (David MacIver) Date: Sun, 08 Feb 2015 12:14:28 -0000 Subject: [Pytest-commit] Issue #677: Different interaction between fixtures, functools.wraps and default arguments in python 2 and 3 (hpk42/pytest) Message-ID: <20150208121428.27450.61518@app07.ash-private.bitbucket.org> New issue 677: Different interaction between fixtures, functools.wraps and default arguments in python 2 and 3 https://bitbucket.org/hpk42/pytest/issue/677/different-interaction-between-fixtures David MacIver: ``` #!python from functools import wraps def add_default(f): @wraps(f) def hello(x=1): return f(x) return hello @add_default def test_hello(x): assert x == 1 ``` In python 2 the addition of the default works: The test is called with x=1. In python 3 this looks for a fixture and errors with fixture 'x' not found. Additionally, if I remove the wraps this works in both versions. I'm not sure what the intended correct behaviour is, but having the behaviour be different between 2 or 3 sounds like a bug regardless of which one is correct. From commits-noreply at bitbucket.org Mon Feb 9 12:13:59 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 09 Feb 2015 11:13:59 -0000 Subject: [Pytest-commit] commit/tox: hpk42: Merged in fschulze/tox/echo-captured-output (pull request #132) Message-ID: <20150209111359.21780.27381@app05.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/27b8bdcddd6a/ Changeset: 27b8bdcddd6a User: hpk42 Date: 2015-02-09 11:13:56+00:00 Summary: Merged in fschulze/tox/echo-captured-output (pull request #132) Add ``--result-tee`` option to echo output captured for the json result to stdout. Affected #: 3 files diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ - refine determination if we run from Jenkins, thanks Borge Lanes. +- echo output to stdout when ``--report-json`` is used 1.8.1 ----------- diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -11,6 +11,7 @@ import os import sys import subprocess +import time from tox._verlib import NormalizedVersion, IrrationalVersionError from tox._venv import VirtualEnv from tox._config import parseconfig @@ -79,7 +80,7 @@ return f def popen(self, args, cwd=None, env=None, redirect=True, returnout=False): - f = outpath = None + stdout = outpath = None resultjson = self.session.config.option.resultjson if resultjson or redirect: f = self._initlogpath(self.id) @@ -87,14 +88,18 @@ self.id, self.msg, args, env)) f.flush() self.popen_outpath = outpath = py.path.local(f.name) + if resultjson: + stdout = subprocess.PIPE + else: + stdout = f elif returnout: - f = subprocess.PIPE + stdout = subprocess.PIPE if cwd is None: # XXX cwd = self.session.config.cwd cwd = py.path.local() try: popen = self._popen(args, cwd, env=env, - stdout=f, stderr=STDOUT) + stdout=stdout, stderr=STDOUT) except OSError as e: self.report.error("invocation failed (errno %d), args: %s, cwd: %s" % (e.errno, args, cwd)) @@ -107,7 +112,28 @@ try: self.report.logpopen(popen, env=env) try: - out, err = popen.communicate() + if resultjson and not redirect: + assert popen.stderr is None # prevent deadlock + out = None + last_time = time.time() + while 1: + # we have to read one byte at a time, otherwise there + # might be no output for a long time with slow tests + data = popen.stdout.read(1) + if data: + sys.stdout.write(data) + if '\n' in data or (time.time() - last_time) > 5: + # we flush on newlines or after 5 seconds to + # provide quick enough feedback to the user + # when printing a dot per test + sys.stdout.flush() + last_time = time.time() + f.write(data) + elif popen.poll() is not None: + popen.stdout.close() + break + else: + out, err = popen.communicate() except KeyboardInterrupt: self.report.keyboard_interrupt() popen.wait() Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 9 12:13:59 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 09 Feb 2015 11:13:59 -0000 Subject: [Pytest-commit] commit/tox: 5 new changesets Message-ID: <20150209111359.15324.41390@app01.ash-private.bitbucket.org> 5 new commits in tox: https://bitbucket.org/hpk42/tox/commits/f6f6e21a6172/ Changeset: f6f6e21a6172 Branch: echo-captured-output User: fschulze Date: 2015-01-29 12:59:26+00:00 Summary: Add ``--result-tee`` option to echo output captured for the json result to stdout. Affected #: 2 files diff -r df35850bb8d3d8a482f4415a6cab86dad23c951a -r f6f6e21a6172a3ad3dd264746123f0660576dd69 tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -11,6 +11,7 @@ import os import sys import subprocess +import time from tox._verlib import NormalizedVersion, IrrationalVersionError from tox._venv import VirtualEnv from tox._config import parseconfig @@ -80,20 +81,24 @@ def popen(self, args, cwd=None, env=None, redirect=True, returnout=False): logged_command = "%s$ %s" %(cwd, " ".join(map(str, args))) - f = outpath = None + stdout = outpath = None resultjson = self.session.config.option.resultjson + resulttee = self.session.config.option.resulttee if resultjson or redirect: f = self._initlogpath(self.id) f.write("actionid=%s\nmsg=%s\ncmdargs=%r\nenv=%s\n" %( self.id, self.msg, args, env)) f.flush() self.popen_outpath = outpath = py.path.local(f.name) + stdout = f elif returnout: - f = subprocess.PIPE + stdout = subprocess.PIPE + if resultjson and resulttee: + stdout = subprocess.PIPE if cwd is None: # XXX cwd = self.session.config.cwd cwd = py.path.local() - popen = self._popen(args, cwd, env=env, stdout=f, stderr=STDOUT) + popen = self._popen(args, cwd, env=env, stdout=stdout, stderr=STDOUT) popen.outpath = outpath popen.args = [str(x) for x in args] popen.cwd = cwd @@ -102,7 +107,23 @@ try: self.report.logpopen(popen, env=env) try: - out, err = popen.communicate() + if resultjson and resulttee: + assert popen.stderr is None # prevent deadlock + out = None + last_time = time.time() + while 1: + data = popen.stdout.read(1) + if data: + sys.stdout.write(data) + if '\n' in data or (time.time() - last_time) > 5: + sys.stdout.flush() + last_time = time.time() + f.write(data) + elif popen.poll() is not None: + popen.stdout.close() + break + else: + out, err = popen.communicate() except KeyboardInterrupt: self.report.keyboard_interrupt() popen.wait() diff -r df35850bb8d3d8a482f4415a6cab86dad23c951a -r f6f6e21a6172a3ad3dd264746123f0660576dd69 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -116,6 +116,9 @@ "all commands and results involved. This will turn off " "pass-through output from running test commands which is " "instead captured into the json result file.") + parser.add_argument("--result-tee", action="store_true", + dest="resulttee", + help="echo output of --result-json to stdout while it is captured.") parser.add_argument("args", nargs="*", help="additional arguments available to command positional substitution") return parser https://bitbucket.org/hpk42/tox/commits/8b053b6f34d4/ Changeset: 8b053b6f34d4 Branch: echo-captured-output User: fschulze Date: 2015-01-29 13:25:16+00:00 Summary: Merged default Affected #: 36 files diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf .hgignore --- a/.hgignore +++ b/.hgignore @@ -14,3 +14,4 @@ doc/_build/ tox.egg-info .tox +.cache diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf .hgtags --- a/.hgtags +++ b/.hgtags @@ -15,3 +15,8 @@ 8fcc1bed3e918b625d85864cc3f4623578852e7e 1.5.0 33e5e5dff406e699893a65ecd5044d3eee35b69b 1.6.0 2e580ee6feea934cc2e683635abded27c0de0be9 1.6.1 +5b4e536b8d3810c791b742b2a8723c53b8d3d720 1.7.0 +c7155565c89d1bb3684c881ca774d921188223a0 1.7.1 +e319e464470a5885505ab3e1da1a3a7abe5f86e2 1.7.2 +b7374e501bde055c5c2b572e6512d22e10f60088 1.8.0 +2aa9b587d12ae4b325cb4d5a9a801a222ffc328c 1.8.1 diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,139 @@ -1.6.2.dev +1.9.0.dev +----------- + +- fix issue193: Remove ``--pre`` from the default ``install_command``; by + default tox will now only install final releases from PyPI for unpinned + dependencies. Use ``pip_pre = true`` in a testenv or the ``--pre`` + command-line option to restore the previous behavior. + +- fix issue199: fill resultlog structure ahead of virtualenv creation + +- refine determination if we run from Jenkins, thanks Borge Lanes. + + +1.8.1 +----------- + +- fix issue190: allow setenv to be empty. + +- allow escaping curly braces with "\". Thanks Marc Abramowitz for the PR. + +- allow "." names in environment names such that "py27-django1.7" is a + valid environment name. Thanks Alex Gaynor and Alex Schepanovski. + +- report subprocess exit code when execution fails. Thanks Marius + Gedminas. + +1.8.0 +----------- + +- new multi-dimensional configuration support. Many thanks to + Alexander Schepanovski for the complete PR with docs. + And to Mike Bayer and others for testing and feedback. + +- fix issue148: remove "__PYVENV_LAUNCHER__" from os.environ when starting + subprocesses. Thanks Steven Myint. + +- fix issue152: set VIRTUAL_ENV when running test commands, + thanks Florian Ludwig. + +- better report if we can't get version_info from an interpreter + executable. Thanks Floris Bruynooghe. + + +1.7.2 +----------- + +- fix issue150: parse {posargs} more like we used to do it pre 1.7.0. + The 1.7.0 behaviour broke a lot of OpenStack projects. + See PR85 and the issue discussions for (far) more details, hopefully + resulting in a more refined behaviour in the 1.8 series. + And thanks to Clark Boylan for the PR. + +- fix issue59: add a config variable ``skip-missing-interpreters`` as well as + command line option ``--skip-missing-interpreters`` which won't fail the + build if Python interpreters listed in tox.ini are missing. Thanks + Alexandre Conrad for PR104. + +- fix issue164: better traceback info in case of failing test commands. + Thanks Marc Abramowitz for PR92. + +- support optional env variable substitution, thanks Morgan Fainberg + for PR86. + +- limit python hashseed to 1024 on Windows to prevent possible + memory errors. Thanks March Schlaich for the PR90. + +1.7.1 --------- +- fix issue162: don't list python 2.5 as compatibiliy/supported + +- fix issue158 and fix issue155: windows/virtualenv properly works now: + call virtualenv through "python -m virtualenv" with the same + interpreter which invoked tox. Thanks Chris Withers, Ionel Maries Cristian. + +1.7.0 +--------- + +- don't lookup "pip-script" anymore but rather just "pip" on windows + as this is a pip implementation detail and changed with pip-1.5. + It might mean that tox-1.7 is not able to install a different pip + version into a virtualenv anymore. + +- drop Python2.5 compatibility because it became too hard due + to the setuptools-2.0 dropping support. tox now has no + support for creating python2.5 based environments anymore + and all internal special-handling has been removed. + +- merged PR81: new option --force-dep which allows to + override tox.ini specified dependencies in setuptools-style. + For example "--force-dep 'django<1.6'" will make sure + that any environment using "django" as a dependency will + get the latest 1.5 release. Thanks Bruno Oliveria for + the complete PR. + +- merged PR125: tox now sets "PYTHONHASHSEED" to a random value + and offers a "--hashseed" option to repeat a test run with a specific seed. + You can also use --hashsheed=noset to instruct tox to leave the value + alone. Thanks Chris Jerdonek for all the work behind this. + +- fix issue132: removing zip_safe setting (so it defaults to false) + to allow installation of tox + via easy_install/eggs. Thanks Jenisys. + +- fix issue126: depend on virtualenv>=1.11.2 so that we can rely + (hopefully) on a pip version which supports --pre. (tox by default + uses to --pre). also merged in PR84 so that we now call "virtualenv" + directly instead of looking up interpreters. Thanks Ionel Maries Cristian. + This also fixes issue140. + +- fix issue130: you can now set install_command=easy_install {opts} {packages} + and expect it to work for repeated tox runs (previously it only worked + when always recreating). Thanks jenisys for precise reporting. + +- fix issue129: tox now uses Popen(..., universal_newlines=True) to force + creation of unicode stdout/stderr streams. fixes a problem on specific + platform configs when creating virtualenvs with Python3.3. Thanks + Jorgen Sch?fer or investigation and solution sketch. + - fix issue128: enable full substitution in install_command, thanks for the PR to Ronald Evers +- rework and simplify "commands" parsing and in particular posargs + substitutions to avoid various win32/posix related quoting issues. + +- make sure that the --installpkg option trumps any usedevelop settings + in tox.ini or + +- introduce --no-network to tox's own test suite to skip tests + requiring networks + +- introduce --sitepackages to force sitepackages=True in all + environments. + +- fix issue105 -- don't depend on an existing HOME directory from tox tests. + 1.6.1 ----- diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3,6 +3,7 @@ Krisztian Fekete Marc Abramowitz +Aleaxner Schepanovski Sridhar Ratnakumar Barry Warsaw Chris Rose @@ -11,3 +12,20 @@ Lukasz Balcerzak Philip Thiem Monty Taylor +Bruno Oliveira +Ionel Maries Cristian +Anatoly techntonik +Matt Jeffery +Chris Jerdonek +Ronald Evers +Carl Meyer +Anthon van der Neuth +Matt Good +Mattieu Agopian +Asmund Grammeltwedt +Ionel Maries Cristian +Alexandre Conrad +Morgan Fainberg +Marc Schlaich +Clark Boylan +Eugene Yunak diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf README.rst --- a/README.rst +++ b/README.rst @@ -21,5 +21,5 @@ have fun, -holger krekel, May 2013 +holger krekel, 2014 diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/announce/release-1.8.txt --- /dev/null +++ b/doc/announce/release-1.8.txt @@ -0,0 +1,54 @@ +tox 1.8: Generative/combinatorial environments specs +============================================================================= + +I am happy to announce tox 1.8 which implements parametrized environments. + +See https://tox.testrun.org/latest/config.html#generating-environments-conditional-settings +for examples and the new backward compatible syntax in your tox.ini file. + +Many thanks to Alexander Schepanovski for implementing and refining +it based on the specifcation draft. + +More documentation about tox in general: + + http://tox.testrun.org/ + +Installation: + + pip install -U tox + +code hosting and issue tracking on bitbucket: + + https://bitbucket.org/hpk42/tox + +What is tox? +---------------- + +tox standardizes and automates tedious test activities driven from a +simple ``tox.ini`` file, including: + +* creation and management of different virtualenv environments + with different Python interpreters +* packaging and installing your package into each of them +* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks +* testing dev packages against each other without needing to upload to PyPI + +best, +Holger Krekel, merlinux GmbH + + +Changes 1.8 (compared to 1.7.2) +--------------------------------------- + +- new multi-dimensional configuration support. Many thanks to + Alexander Schepanovski for the complete PR with docs. + And to Mike Bayer and others for testing and feedback. + +- fix issue148: remove "__PYVENV_LAUNCHER__" from os.environ when starting + subprocesses. Thanks Steven Myint. + +- fix issue152: set VIRTUAL_ENV when running test commands, + thanks Florian Ludwig. + +- better report if we can't get version_info from an interpreter + executable. Thanks Floris Bruynooghe. diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/conf.py --- a/doc/conf.py +++ b/doc/conf.py @@ -48,7 +48,8 @@ # built documents. # # The short X.Y version. -release = version = "1.6.1" +release = "1.8" +version = "1.8.1" # The full version, including alpha/beta/rc tags. # The language for content autogenerated by Sphinx. Refer to documentation diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/config-v2.txt --- a/doc/config-v2.txt +++ b/doc/config-v2.txt @@ -195,7 +195,7 @@ tox comes with predefined settings for certain variants, namely: * ``{easy,pip}`` use easy_install or pip respectively -* ``{py24,py25,py26,py27,py31,py32,py33,pypy19]`` use the respective +* ``{py24,py25,py26,py27,py31,py32,py33,py34,pypy19]`` use the respective pythonNN or PyPy interpreter * ``{win32,linux,darwin}`` defines the according ``platform``. diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -28,20 +28,31 @@ (by checking for existence of the ``JENKINS_URL`` environment variable) and will first lookup global tox settings in this section:: - [tox:hudson] - ... # override [tox] settings for the hudson context - # note: for hudson distshare defaults to ``{toxworkdir}/distshare``. + [tox:jenkins] + ... # override [tox] settings for the jenkins context + # note: for jenkins distshare defaults to ``{toxworkdir}/distshare``. +.. confval:: skip_missing_interpreters=BOOL -envlist setting -+++++++++++++++ + .. versionadded:: 1.7.2 -Determining the environment list that ``tox`` is to operate on -happens in this order: + Setting this to ``True`` is equivalent of passing the + ``--skip-missing-interpreters`` command line option, and will force ``tox`` to + return success even if some of the specified environments were missing. This is + useful for some CI systems or running on a developer box, where you might only + have a subset of all your supported interpreters installed but don't want to + mark the build as failed because of it. As expected, the command line switch + always overrides this setting if passed on the invokation. + **Default:** ``False`` -* command line option ``-eENVLIST`` -* environment variable ``TOXENV`` -* ``tox.ini`` file's ``envlist`` +.. confval:: envlist=CSV + + Determining the environment list that ``tox`` is to operate on + happens in this order (if any is found, no further lookups are made): + + * command line option ``-eENVLIST`` + * environment variable ``TOXENV`` + * ``tox.ini`` file's ``envlist`` Virtualenv test environment settings @@ -80,7 +91,7 @@ .. versionadded:: 1.6 - **WARNING**: This setting is **EXPERIMENTAL** so use with care + **WARNING**: This setting is **EXPERIMENTAL** so use with care and be ready to adapt your tox.ini's with post-1.6 tox releases. the ``install_command`` setting is used for installing packages into @@ -94,22 +105,29 @@ if you have configured it. **default**:: - - pip install --pre {opts} {packages} - - **default on environments using python2.5**:: - pip install {opts} {packages}`` + pip install {opts} {packages} - this will use pip<1.4 which has no ``--pre`` option. Note also - that for python2.5 support you may need to install ssl and/or - use ``setenv = PIP_INSECURE=1`` in a py25 based testenv. +.. confval:: pip_pre=True|False(default) + + .. versionadded:: 1.9 + + If ``True``, adds ``--pre`` to the ``opts`` passed to + :confval:`install_command`. If :confval:`install_command` uses pip, this + will cause it to install the latest available pre-release of any + dependencies without a specified version. If ``False`` (the default), pip + will only install final releases of unpinned dependencies. + + Passing the ``--pre`` command-line option to tox will force this to + ``True`` for all testenvs. + + Don't set this option if your :confval:`install_command` does not use pip. .. confval:: whitelist_externals=MULTI-LINE-LIST each line specifies a command name (in glob-style pattern format) which can be used in the ``commands`` section without triggering - a "not installed in virtualenv" warning. Example: if you use the + a "not installed in virtualenv" warning. Example: if you use the unix ``make`` for running tests you can list ``whitelist_externals=make`` or ``whitelist_externals=/usr/bin/make`` if you want more precision. If you don't want tox to issue a warning in any case, just use @@ -136,7 +154,7 @@ using the ``{toxinidir}`` as the current working directory. .. confval:: setenv=MULTI-LINE-LIST - + .. versionadded:: 0.9 each line contains a NAME=VALUE environment variable setting which @@ -164,17 +182,17 @@ **DEPRECATED** -- as of August 2013 you should use setuptools which has merged most of distribute_ 's changes. Just use - the default, Luke! In future versions of tox this option might - be ignored and setuptools always chosen. + the default, Luke! In future versions of tox this option might + be ignored and setuptools always chosen. **default:** False. .. confval:: sitepackages=True|False Set to ``True`` if you want to create virtual environments that also - have access to globally installed packages. + have access to globally installed packages. - **default:** False, meaning that virtualenvs will be + **default:** False, meaning that virtualenvs will be created without inheriting the global site packages. .. confval:: args_are_paths=BOOL @@ -182,7 +200,7 @@ treat positional arguments passed to ``tox`` as file system paths and - if they exist on the filesystem - rewrite them according to the ``changedir``. - **default**: True (due to the exists-on-filesystem check it's + **default**: True (due to the exists-on-filesystem check it's usually safe to try rewriting). .. confval:: envtmpdir=path @@ -202,7 +220,7 @@ .. versionadded:: 0.9 Multi-line ``name = URL`` definitions of python package servers. - Depedencies can specify using a specified index server through the + Dependencies can specify using a specified index server through the ``:indexservername:depname`` pattern. The ``default`` indexserver definition determines where unscoped dependencies and the sdist install installs from. Example:: @@ -241,6 +259,10 @@ Any ``key=value`` setting in an ini-file can make use of value substitution through the ``{...}`` string-substitution pattern. +You can escape curly braces with the ``\`` character if you need them, for example:: + + commands = echo "\{posargs\}" = {posargs} + Globally available substitutions ++++++++++++++++++++++++++++++++ @@ -292,6 +314,26 @@ and raise an Error if the environment variable does not exist. + +environment variable substitutions with default values +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +If you specify a substitution string like this:: + + {env:KEY:DEFAULTVALUE} + +then the value will be retrieved as ``os.environ['KEY']`` +and replace with DEFAULTVALUE if the environment variable does not +exist. + +If you specify a substitution string like this:: + + {env:KEY:} + +then the value will be retrieved as ``os.environ['KEY']`` +and replace with and empty string if the environment variable does not +exist. + .. _`command positional substitution`: .. _`positional substitution`: @@ -347,7 +389,7 @@ pytest mock pytest-xdist - + [testenv:dulwich] deps = dulwich @@ -359,6 +401,152 @@ {[base]deps} +Generating environments, conditional settings +--------------------------------------------- + +.. versionadded:: 1.8 + +Suppose you want to test your package against python2.6, python2.7 and against +several versions of a dependency, say Django 1.5 and Django 1.6. You can +accomplish that by writing down 2*2 = 4 ``[testenv:*]`` sections and then +listing all of them in ``envlist``. + +However, a better approach looks like this:: + + [tox] + envlist = {py26,py27}-django{15,16} + + [testenv] + basepython = + py26: python2.6 + py27: python2.7 + deps = + pytest + django15: Django>=1.5,<1.6 + django16: Django>=1.6,<1.7 + py26: unittest2 + commands = py.test + +This uses two new facilities of tox-1.8: + +- generative envlist declarations where each envname + consists of environment parts or "factors" + +- "factor" specific settings + +Let's go through this step by step. + + +Generative envlist ++++++++++++++++++++++++ + +:: + + envlist = {py26,py27}-django{15,16} + +This is bash-style syntax and will create ``2*2=4`` environment names +like this:: + + py26-django15 + py26-django16 + py27-django15 + py27-django16 + +You can still list environments explicitly along with generated ones:: + + envlist = {py26,py27}-django{15,16}, docs, flake + +.. note:: + + To help with understanding how the variants will produce section values, + you can ask tox to show their expansion with a new option:: + + $ tox -l + py26-django15 + py26-django16 + py27-django15 + py27-django16 + docs + flake + + +Factors and factor-conditional settings +++++++++++++++++++++++++++++++++++++++++ + +Parts of an environment name delimited by hyphens are called factors and can +be used to set values conditionally:: + + basepython = + py26: python2.6 + py27: python2.7 + +This conditional setting will lead to either ``python2.6`` or +``python2.7`` used as base python, e.g. ``python2.6`` is selected if current +environment contains ``py26`` factor. + +In list settings such as ``deps`` or ``commands`` you can freely intermix +optional lines with unconditional ones:: + + deps = + pytest + django15: Django>=1.5,<1.6 + django16: Django>=1.6,<1.7 + py26: unittest2 + +Reading it line by line: + +- ``pytest`` will be included unconditionally, +- ``Django>=1.5,<1.6`` will be included for environments containing ``django15`` factor, +- ``Django>=1.6,<1.7`` similarly depends on ``django16`` factor, +- ``unittest`` will be loaded for Python 2.6 environments. + +.. note:: + + Tox provides good defaults for basepython setting, so the above + ini-file can be further reduced by omitting the ``basepython`` + setting. + + +Complex factor conditions ++++++++++++++++++++++++++ + +Sometimes you need to specify same line for several factors or create a special +case for a combination of factors. Here is how you do it:: + + [tox] + envlist = py{26,27,33}-django{15,16}-{sqlite,mysql} + + [testenv] + deps = + py33-mysql: PyMySQL ; use if both py33 and mysql are in an env name + py26,py27: urllib3 ; use if any of py26 or py27 are in an env name + py{26,27}-sqlite: mock ; mocking sqlite in python 2.x + +Take a look at first ``deps`` line. It shows how you can special case something +for a combination of factors, you just join combining factors with a hyphen. +This particular line states that ``PyMySQL`` will be loaded for python 3.3, +mysql environments, e.g. ``py33-django15-mysql`` and ``py33-django16-mysql``. + +The second line shows how you use same line for several factors - by listing +them delimited by commas. It's possible to list not only simple factors, but +also their combinations like ``py26-sqlite,py27-sqlite``. + +Finally, factor expressions are expanded the same way as envlist, so last +example could be rewritten as ``py{26,27}-sqlite``. + +.. note:: + + Factors don't do substring matching against env name, instead every + hyphenated expression is split by ``-`` and if ALL the factors in an + expression are also factors of an env then that condition is considered + hold. + + For example, environment ``py26-mysql``: + + - could be matched with expressions ``py26``, ``py26-mysql``, + ``mysql-py26``, + - but not with ``py2`` or ``py26-sql``. + Other Rules and notes ===================== diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/example/basic.txt --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -1,4 +1,3 @@ - Basic usage ============================================= @@ -13,6 +12,7 @@ [tox] envlist = py26,py27 [testenv] + deps=pytest # or 'nose' or ... commands=py.test # or 'nosetests' or ... To sdist-package, install and test your project, you can @@ -38,8 +38,10 @@ py31 py32 py33 + py34 jython pypy + pypy3 However, you can also create your own test environment names, see some of the examples in :doc:`examples <../examples>`. @@ -74,7 +76,7 @@ deps = -rrequirements.txt -All installation commands are executed using ``{toxinidir}}`` +All installation commands are executed using ``{toxinidir}`` (the directory where ``tox.ini`` resides) as the current working directory. Therefore, the underlying ``pip`` installation will assume ``requirements.txt`` to exist at ``{toxinidir}/requirements.txt``. @@ -175,6 +177,31 @@ from the ``subdir`` below the directory where your ``tox.ini`` file resides. +special handling of PYTHONHASHSEED +------------------------------------------- + +.. versionadded:: 1.6.2 + +By default, Tox sets PYTHONHASHSEED_ for test commands to a random integer +generated when ``tox`` is invoked. This mimics Python's hash randomization +enabled by default starting `in Python 3.3`_. To aid in reproducing test +failures, Tox displays the value of ``PYTHONHASHSEED`` in the test output. + +You can tell Tox to use an explicit hash seed value via the ``--hashseed`` +command-line option to ``tox``. You can also override the hash seed value +per test environment in ``tox.ini`` as follows:: + + [testenv] + setenv = + PYTHONHASHSEED = 100 + +If you wish to disable this feature, you can pass the command line option +``--hashseed=noset`` when ``tox`` is invoked. You can also disable it from the +``tox.ini`` by setting ``PYTHONHASHSEED = 0`` as described above. + +.. _`in Python 3.3`: http://docs.python.org/3/whatsnew/3.3.html#builtin-functions-and-types +.. _PYTHONHASHSEED: http://docs.python.org/using/cmdline.html#envvar-PYTHONHASHSEED + Integration with setuptools/distribute test commands ---------------------------------------------------- @@ -186,6 +213,10 @@ import sys class Tox(TestCommand): + user_options = [('tox-args=', 'a', "Arguments to pass to tox")] + def initialize_options(self): + TestCommand.initialize_options(self) + self.tox_args = None def finalize_options(self): TestCommand.finalize_options(self) self.test_args = [] @@ -193,7 +224,8 @@ def run_tests(self): #import here, cause outside the eggs aren't loaded import tox - errno = tox.cmdline(self.test_args) + import shlex + errno = tox.cmdline(args=shlex.split(self.tox_args)) sys.exit(errno) setup( @@ -206,5 +238,9 @@ python setup.py test -this will install tox and then run tox. +this will install tox and then run tox. You can pass arguments to ``tox`` +using the ``--tox-args`` or ``-a`` command-line options. For example:: + python setup.py test -a "-epy27" + +is equivalent to running ``tox -epy27``. diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/example/devenv.txt --- a/doc/example/devenv.txt +++ b/doc/example/devenv.txt @@ -1,61 +1,78 @@ - +======================= Development environment ======================= -Tox can be used to prepare development virtual environment for local projects. -This feature can be useful in order to preserve environment across team members -working on same project. It can be also used by deployment tools to prepare -proper environments. +Tox can be used for just preparing different virtual environments required by a +project. +This feature can be used by deployment tools when preparing deployed project +environments. It can also be used for setting up normalized project development +environments and thus help reduce the risk of different team members using +mismatched development environments. -Configuration -------------- +Here are some examples illustrating how to set up a project's development +environment using tox. For illustration purposes, let us call the development +environment ``devenv``. -Firstly, you need to prepare configuration for your development environment. In -order to do that, we must define proper section at ``tox.ini`` file and tell at -what directory environment should be created. Moreover, we need to specify -python version that should be picked, and that the package should be installed -with ``setup.py develop``:: + +Example 1: Basic scenario +========================= + +Step 1 - Configure the development environment +---------------------------------------------- + +First, we prepare the tox configuration for our development environment by +defining a ``[testenv:devenv]`` section in the project's ``tox.ini`` +configuration file:: [testenv:devenv] envdir = devenv basepython = python2.7 usedevelop = True + +In it we state: + +- what directory to locate the environment in, +- what Python executable to use in the environment, +- that our project should be installed into the environment using ``setup.py + develop``, as opposed to building and installing its source distribution using + ``setup.py install``. + +Actually, we can configure a lot more, and these are only the required settings. +For example, we can add the following to our configuration, telling tox not to +reuse ``commands`` or ``deps`` settings from the base ``[testenv]`` +configuration:: + commands = deps = -Actually, you can configure a lot more, those are the only required settings. -In example you can add ``deps`` and ``commands`` settings. Here, we tell tox -not to pick ``commands`` or ``deps`` from base ``testenv`` configuration. +Step 2 - Create the development environment +------------------------------------------- - -Creating development environment --------------------------------- - -Once ``devenv`` section is defined we can instrument tox to create our -environment:: +Once the ``[testenv:devenv]`` configuration section has been defined, we create +the actual development environment by running the following:: tox -e devenv -This will create an environment at path specified by ``envdir`` under -``[testenv:devenv]`` section. +This creates the environment at the path specified by the environment's +``envdir`` configuration value. -Full configuration example --------------------------- +Example 2: A more complex scenario +================================== -Let's say we want our development environment sit at ``devenv`` and pull -packages from ``requirements.txt`` file which we create at the same directory -as ``tox.ini`` file. We also want to speciy Python version to be 2.7, and use -``setup.py develop`` to work in development mode instead of building and -installing an ``sdist`` package. +Let us say we want our project development environment to: -Here is example configuration for that:: +- be located in the ``devenv`` directory, +- use Python executable ``python2.7``, +- pull packages from ``requirements.txt``, located in the same directory as + ``tox.ini``. + +Here is an example configuration for the described scenario:: [testenv:devenv] envdir = devenv basepython = python2.7 usedevelop = True deps = -rrequirements.txt - diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/example/jenkins.txt --- a/doc/example/jenkins.txt +++ b/doc/example/jenkins.txt @@ -32,7 +32,9 @@ The last point requires that your test command creates JunitXML files, for example with ``py.test`` it is done like this: - commands=py.test --junitxml=junit-{envname}.xml +.. code-block:: ini + + commands = py.test --junitxml=junit-{envname}.xml @@ -57,7 +59,7 @@ exec urllib.urlopen(url).read() in d d['cmdline'](['--recreate']) -The downloaded `toxbootstrap.py`_ file downloads all neccessary files to +The downloaded `toxbootstrap.py` file downloads all neccessary files to install ``tox`` in a virtual sub environment. Notes: * uncomment the line containing ``USETOXDEV`` to use the latest @@ -68,7 +70,6 @@ will cause tox to reinstall all virtual environments all the time which is often what one wants in CI server contexts) -.. _`toxbootstrap.py`: https://bitbucket.org/hpk42/tox/raw/default/toxbootstrap.py Integrating "sphinx" documentation checks in a Jenkins job ---------------------------------------------------------------- diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/example/pytest.txt --- a/doc/example/pytest.txt +++ b/doc/example/pytest.txt @@ -23,7 +23,7 @@ deps=pytest # PYPI package providing py.test commands= py.test \ - [] # substitute with tox' positional arguments + {posargs} # substitute with tox' positional arguments you can now invoke ``tox`` in the directory where your ``tox.ini`` resides. ``tox`` will sdist-package your project, create two virtualenv environments @@ -49,7 +49,7 @@ commands= py.test \ --basetemp={envtmpdir} \ # py.test tempdir setting - [] # substitute with tox' positional arguments + {posargs} # substitute with tox' positional arguments you can invoke ``tox`` in the directory where your ``tox.ini`` resides. Differently than in the previous example the ``py.test`` command @@ -73,7 +73,7 @@ --basetemp={envtmpdir} \ --confcutdir=.. \ -n 3 \ # use three sub processes - [] + {posargs} .. _`listed as a known issue`: @@ -99,16 +99,13 @@ files are outside the import path, then pass ``--pyargs mypkg`` to pytest. -Installed tests are particularly convenient when combined with -`Distribute's 2to3 support` (``use_2to3``). +With tests that won't be installed, the simplest way to run them +against your installed package is to avoid ``__init__.py`` files in test +directories; pytest will still find and import them by adding their +parent directory to ``sys.path`` but they won't be copied to +other places or be found by Python's import system outside of pytest. -With tests that won't be installed, the simplest way is to avoid -``__init__.py`` files in test directories; pytest will still find them -but they won't be copied to other places or be found by Python's import -system. +.. _`fully qualified name`: http://pytest.org/latest/goodpractises.html#test-package-name -.. _`fully qualified name`: http://pytest.org/latest/goodpractises.html#package-name - -.. _`Distribute's 2to3 support`: http://packages.python.org/distribute/python3.html .. include:: ../links.txt diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/index.txt --- a/doc/index.txt +++ b/doc/index.txt @@ -1,8 +1,6 @@ Welcome to the tox automation project =============================================== -.. note:: second training: `professional testing with Python `_ , 25-27th November 2013, Leipzig. - vision: standardize testing in Python --------------------------------------------- @@ -70,9 +68,8 @@ support for configuring the installer command through :confval:`install_command=ARGV`. -* **cross-Python compatible**: Python-2.5 up to Python-3.3, - Jython and pypy_ support. Python-2.5 is supported through - a vendored ``virtualenv-1.9.1`` script. +* **cross-Python compatible**: CPython-2.6, 2.7, 3.2 and higher, + Jython and pypy_. * **cross-platform**: Windows and Unix style environments diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf doc/install.txt --- a/doc/install.txt +++ b/doc/install.txt @@ -4,7 +4,7 @@ Install info in a nutshell ---------------------------------- -**Pythons**: CPython 2.4-3.3, Jython-2.5.1, pypy-1.9ff +**Pythons**: CPython 2.6-3.3, Jython-2.5.1, pypy-1.9ff **Operating systems**: Linux, Windows, OSX, Unix diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf setup.py --- a/setup.py +++ b/setup.py @@ -18,17 +18,15 @@ def main(): version = sys.version_info[:2] - install_requires = ['virtualenv>=1.9.1', 'py>=1.4.15', ] - if version < (2, 7) or (3, 0) <= version <= (3, 1): + install_requires = ['virtualenv>=1.11.2', 'py>=1.4.17', ] + if version < (2, 7): install_requires += ['argparse'] - if version < (2,6): - install_requires += ["simplejson"] setup( name='tox', description='virtualenv-based automation of test activities', long_description=open("README.rst").read(), url='http://tox.testrun.org/', - version='1.6.2.dev1', + version='1.8.2.dev1', license='http://opensource.org/licenses/MIT', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], author='holger krekel', @@ -40,7 +38,6 @@ tests_require=['tox'], cmdclass={"test": Tox}, install_requires=install_requires, - zip_safe=True, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf tests/conftest.py --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,2 +1,2 @@ -from tox._pytestplugin import * +from tox._pytestplugin import * # noqa diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf tests/test_config.py --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,11 +1,11 @@ -import tox -import pytest -import os, sys -import subprocess +import sys from textwrap import dedent import py -from tox._config import * +import pytest +import tox +import tox._config +from tox._config import * # noqa from tox._config import _split_env @@ -61,6 +61,43 @@ envconfig = config.envconfigs['devenv'] assert envconfig.envdir == config.toxworkdir.join('foobar') + def test_force_dep_version(self, initproj): + """ + Make sure we can override dependencies configured in tox.ini when using the command line option + --force-dep. + """ + initproj("example123-0.5", filedefs={ + 'tox.ini': ''' + [tox] + + [testenv] + deps= + dep1==1.0 + dep2>=2.0 + dep3 + dep4==4.0 + ''' + }) + config = parseconfig( + ['--force-dep=dep1==1.5', '--force-dep=dep2==2.1', + '--force-dep=dep3==3.0']) + assert config.option.force_dep== [ + 'dep1==1.5', 'dep2==2.1', 'dep3==3.0'] + assert [str(x) for x in config.envconfigs['python'].deps] == [ + 'dep1==1.5', 'dep2==2.1', 'dep3==3.0', 'dep4==4.0', + ] + + def test_is_same_dep(self): + """ + Ensure correct parseini._is_same_dep is working with a few samples. + """ + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>=2.0') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>2.0') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<2.0') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<=2.0') + assert not parseini._is_same_dep('pkg_hello-world3==1.0', 'otherpkg>=2.0') + class TestConfigPackage: def test_defaults(self, tmpdir, newconfig): config = newconfig([], "") @@ -69,10 +106,10 @@ envconfig = config.envconfigs['python'] assert envconfig.args_are_paths assert not envconfig.recreate + assert not envconfig.pip_pre def test_defaults_distshare(self, tmpdir, newconfig): config = newconfig([], "") - envconfig = config.envconfigs['python'] assert config.distshare == config.homedir.join(".tox", "distshare") def test_defaults_changed_dir(self, tmpdir, newconfig): @@ -111,6 +148,20 @@ assert get_homedir() == "123" +class TestGetcontextname: + def test_blank(self, monkeypatch): + monkeypatch.setattr(os, "environ", {}) + assert getcontextname() is None + + def test_jenkins(self, monkeypatch): + monkeypatch.setattr(os, "environ", {"JENKINS_URL": "xyz"}) + assert getcontextname() == "jenkins" + + def test_hudson_legacy(self, monkeypatch): + monkeypatch.setattr(os, "environ", {"HUDSON_URL": "xyz"}) + assert getcontextname() == "jenkins" + + class TestIniParser: def test_getdefault_single(self, tmpdir, newconfig): config = newconfig(""" @@ -130,6 +181,7 @@ key2={xyz} """) reader = IniReader(config._cfg, fallbacksections=['mydefault']) + assert reader is not None py.test.raises(tox.exception.ConfigError, 'reader.getdefault("mydefault", "key2")') @@ -204,6 +256,22 @@ py.test.raises(tox.exception.ConfigError, 'reader.getdefault("section", "key2")') + def test_getdefault_environment_substitution_with_default(self, monkeypatch, newconfig): + monkeypatch.setenv("KEY1", "hello") + config = newconfig(""" + [section] + key1={env:KEY1:DEFAULT_VALUE} + key2={env:KEY2:DEFAULT_VALUE} + key3={env:KEY3:} + """) + reader = IniReader(config._cfg) + x = reader.getdefault("section", "key1") + assert x == "hello" + x = reader.getdefault("section", "key2") + assert x == "DEFAULT_VALUE" + x = reader.getdefault("section", "key3") + assert x == "" + def test_getdefault_other_section_substitution(self, newconfig): config = newconfig(""" [section] @@ -240,9 +308,19 @@ # "reader.getargvlist('section', 'key1')") assert reader.getargvlist('section', 'key1') == [] x = reader.getargvlist("section", "key2") - assert x == [["cmd1", "with space", "grr"], + assert x == [["cmd1", "with", "space", "grr"], ["cmd2", "grr"]] + def test_argvlist_windows_escaping(self, tmpdir, newconfig): + config = newconfig(""" + [section] + comm = py.test {posargs} + """) + reader = IniReader(config._cfg) + reader.addsubstitutions([r"hello\this"]) + argv = reader.getargv("section", "comm") + assert argv == ["py.test", "hello\\this"] + def test_argvlist_multiline(self, tmpdir, newconfig): config = newconfig(""" [section] @@ -256,7 +334,7 @@ # "reader.getargvlist('section', 'key1')") assert reader.getargvlist('section', 'key1') == [] x = reader.getargvlist("section", "key2") - assert x == [["cmd1", "with space", "grr"]] + assert x == [["cmd1", "with", "space", "grr"]] def test_argvlist_quoting_in_command(self, tmpdir, newconfig): @@ -298,7 +376,36 @@ assert argvlist[0] == ["cmd1"] assert argvlist[1] == ["cmd2", "value2", "other"] - def test_positional_arguments_are_only_replaced_when_standing_alone(self, tmpdir, newconfig): + def test_argvlist_quoted_posargs(self, tmpdir, newconfig): + config = newconfig(""" + [section] + key2= + cmd1 --foo-args='{posargs}' + cmd2 -f '{posargs}' + cmd3 -f {posargs} + """) + reader = IniReader(config._cfg) + reader.addsubstitutions(["foo", "bar"]) + assert reader.getargvlist('section', 'key1') == [] + x = reader.getargvlist("section", "key2") + assert x == [["cmd1", "--foo-args=foo bar"], + ["cmd2", "-f", "foo bar"], + ["cmd3", "-f", "foo", "bar"]] + + def test_argvlist_posargs_with_quotes(self, tmpdir, newconfig): + config = newconfig(""" + [section] + key2= + cmd1 -f {posargs} + """) + reader = IniReader(config._cfg) + reader.addsubstitutions(["foo", "'bar", "baz'"]) + assert reader.getargvlist('section', 'key1') == [] + x = reader.getargvlist("section", "key2") + assert x == [["cmd1", "-f", "foo", "bar baz"]] + + def test_positional_arguments_are_only_replaced_when_standing_alone(self, + tmpdir, newconfig): config = newconfig(""" [section] key= @@ -394,7 +501,25 @@ assert envconfig.sitepackages == False assert envconfig.develop == False assert envconfig.envlogdir == envconfig.envdir.join("log") - assert envconfig.setenv is None + assert list(envconfig.setenv.keys()) == ['PYTHONHASHSEED'] + hashseed = envconfig.setenv['PYTHONHASHSEED'] + assert isinstance(hashseed, str) + # The following line checks that hashseed parses to an integer. + int_hashseed = int(hashseed) + # hashseed is random by default, so we can't assert a specific value. + assert int_hashseed > 0 + + def test_sitepackages_switch(self, tmpdir, newconfig): + config = newconfig(["--sitepackages"], "") + envconfig = config.envconfigs['python'] + assert envconfig.sitepackages == True + + def test_installpkg_tops_develop(self, newconfig): + config = newconfig(["--installpkg=abc"], """ + [testenv] + usedevelop = True + """) + assert not config.envconfigs["python"].develop def test_specific_command_overrides(self, tmpdir, newconfig): config = newconfig(""" @@ -444,7 +569,7 @@ envconfig = config.envconfigs['python'] assert envconfig.envpython == envconfig.envbindir.join("python") - @pytest.mark.parametrize("bp", ["jython", "pypy"]) + @pytest.mark.parametrize("bp", ["jython", "pypy", "pypy3"]) def test_envbindir_jython(self, tmpdir, newconfig, bp): config = newconfig(""" [testenv] @@ -484,36 +609,6 @@ assert envconfig.changedir.basename == "abc" assert envconfig.changedir == config.setupdir.join("abc") - def test_install_command_defaults_py25(self, newconfig, monkeypatch): - from tox.interpreters import Interpreters - def get_info(self, name): - if "x25" in name: - class I: - runnable = True - executable = "python2.5" - version_info = (2,5) - else: - class I: - runnable = False - executable = "python" - return I - monkeypatch.setattr(Interpreters, "get_info", get_info) - config = newconfig(""" - [testenv:x25] - basepython = x25 - [testenv:py25-x] - basepython = x25 - [testenv:py26] - basepython = "python" - """) - for name in ("x25", "py25-x"): - env = config.envconfigs[name] - assert env.install_command == \ - "pip install {opts} {packages}".split() - env = config.envconfigs["py26"] - assert env.install_command == \ - "pip install --pre {opts} {packages}".split() - def test_install_command_setting(self, newconfig): config = newconfig(""" [testenv] @@ -540,6 +635,24 @@ 'some_install', '--arg=%s/foo' % config.toxinidir, 'python', '{opts}', '{packages}'] + def test_pip_pre(self, newconfig): + config = newconfig(""" + [testenv] + pip_pre=true + """) + envconfig = config.envconfigs['python'] + assert envconfig.pip_pre + + def test_pip_pre_cmdline_override(self, newconfig): + config = newconfig( + ['--pre'], + """ + [testenv] + pip_pre=false + """) + envconfig = config.envconfigs['python'] + assert envconfig.pip_pre + def test_downloadcache(self, newconfig, monkeypatch): monkeypatch.delenv("PIP_DOWNLOAD_CACHE", raising=False) config = newconfig(""" @@ -567,14 +680,14 @@ def test_simple(tmpdir, newconfig): config = newconfig(""" - [testenv:py24] - basepython=python2.4 - [testenv:py25] - basepython=python2.5 + [testenv:py26] + basepython=python2.6 + [testenv:py27] + basepython=python2.7 """) assert len(config.envconfigs) == 2 - assert "py24" in config.envconfigs - assert "py25" in config.envconfigs + assert "py26" in config.envconfigs + assert "py27" in config.envconfigs def test_substitution_error(tmpdir, newconfig): py.test.raises(tox.exception.ConfigError, newconfig, """ @@ -626,6 +739,23 @@ assert argv[0] == ["cmd1", "[hello]", "world"] assert argv[1] == ["cmd1", "brave", "new", "world"] + def test_posargs_backslashed_or_quoted(self, tmpdir, newconfig): + inisource = """ + [testenv:py24] + commands = + echo "\{posargs\}" = {posargs} + echo "posargs = " "{posargs}" + """ + conf = newconfig([], inisource).envconfigs['py24'] + argv = conf.commands + assert argv[0] == ['echo', '\\{posargs\\}', '='] + assert argv[1] == ['echo', 'posargs = ', ""] + + conf = newconfig(['dog', 'cat'], inisource).envconfigs['py24'] + argv = conf.commands + assert argv[0] == ['echo', '\\{posargs\\}', '=', 'dog', 'cat'] + assert argv[1] == ['echo', 'posargs = ', 'dog cat'] + def test_rewrite_posargs(self, tmpdir, newconfig): inisource = """ [testenv:py24] @@ -752,6 +882,100 @@ assert conf.changedir.basename == 'testing' assert conf.changedir.dirpath().realpath() == tmpdir.realpath() + def test_factors(self, newconfig): + inisource=""" + [tox] + envlist = a-x,b + + [testenv] + deps= + dep-all + a: dep-a + b: dep-b + x: dep-x + """ + conf = newconfig([], inisource) + configs = conf.envconfigs + assert [dep.name for dep in configs['a-x'].deps] == \ + ["dep-all", "dep-a", "dep-x"] + assert [dep.name for dep in configs['b'].deps] == ["dep-all", "dep-b"] + + def test_factor_ops(self, newconfig): + inisource=""" + [tox] + envlist = {a,b}-{x,y} + + [testenv] + deps= + a,b: dep-a-or-b + a-x: dep-a-and-x + {a,b}-y: dep-ab-and-y + """ + configs = newconfig([], inisource).envconfigs + get_deps = lambda env: [dep.name for dep in configs[env].deps] + assert get_deps("a-x") == ["dep-a-or-b", "dep-a-and-x"] + assert get_deps("a-y") == ["dep-a-or-b", "dep-ab-and-y"] + assert get_deps("b-x") == ["dep-a-or-b"] + assert get_deps("b-y") == ["dep-a-or-b", "dep-ab-and-y"] + + def test_default_factors(self, newconfig): + inisource=""" + [tox] + envlist = py{26,27,33,34}-dep + + [testenv] + deps= + dep: dep + """ + conf = newconfig([], inisource) + configs = conf.envconfigs + for name, config in configs.items(): + assert config.basepython == 'python%s.%s' % (name[2], name[3]) + + @pytest.mark.issue188 + def test_factors_in_boolean(self, newconfig): + inisource=""" + [tox] + envlist = py{27,33} + + [testenv] + recreate = + py27: True + """ + configs = newconfig([], inisource).envconfigs + assert configs["py27"].recreate + assert not configs["py33"].recreate + + @pytest.mark.issue190 + def test_factors_in_setenv(self, newconfig): + inisource=""" + [tox] + envlist = py27,py26 + + [testenv] + setenv = + py27: X = 1 + """ + configs = newconfig([], inisource).envconfigs + assert configs["py27"].setenv["X"] == "1" + assert "X" not in configs["py26"].setenv + + def test_period_in_factor(self, newconfig): + inisource=""" + [tox] + envlist = py27-{django1.6,django1.7} + + [testenv] + deps = + django1.6: Django==1.6 + django1.7: Django==1.7 + """ + configs = newconfig([], inisource).envconfigs + assert sorted(configs) == ["py27-django1.6", "py27-django1.7"] + assert [d.name for d in configs["py27-django1.6"].deps] \ + == ["Django==1.6"] + + class TestGlobalOptions: def test_notest(self, newconfig): config = newconfig([], "") @@ -836,7 +1060,7 @@ assert str(env.basepython) == sys.executable def test_default_environments(self, tmpdir, newconfig, monkeypatch): - envs = "py24,py25,py26,py27,py31,py32,jython,pypy" + envs = "py26,py27,py31,py32,py33,py34,jython,pypy,pypy3" inisource = """ [tox] envlist = %s @@ -848,13 +1072,30 @@ env = config.envconfigs[name] if name == "jython": assert env.basepython == "jython" - elif name == "pypy": - assert env.basepython == "pypy" + elif name.startswith("pypy"): + assert env.basepython == name else: assert name.startswith("py") bp = "python%s.%s" %(name[2], name[3]) assert env.basepython == bp + def test_envlist_expansion(self, newconfig): + inisource = """ + [tox] + envlist = py{26,27},docs + """ + config = newconfig([], inisource) + assert config.envlist == ["py26", "py27", "docs"] + + def test_envlist_cross_product(self, newconfig): + inisource = """ + [tox] + envlist = py{26,27}-dep{1,2} + """ + config = newconfig([], inisource) + assert config.envlist == \ + ["py26-dep1", "py26-dep2", "py27-dep1", "py27-dep2"] + def test_minversion(self, tmpdir, newconfig, monkeypatch): inisource = """ [tox] @@ -863,6 +1104,22 @@ config = newconfig([], inisource) assert config.minversion == "3.0" + def test_skip_missing_interpreters_true(self, tmpdir, newconfig, monkeypatch): + inisource = """ + [tox] + skip_missing_interpreters = True + """ + config = newconfig([], inisource) + assert config.option.skip_missing_interpreters + + def test_skip_missing_interpreters_false(self, tmpdir, newconfig, monkeypatch): + inisource = """ + [tox] + skip_missing_interpreters = False + """ + config = newconfig([], inisource) + assert not config.option.skip_missing_interpreters + def test_defaultenv_commandline(self, tmpdir, newconfig, monkeypatch): config = newconfig(["-epy24"], "") env = config.envconfigs['py24'] @@ -881,6 +1138,123 @@ assert env.basepython == "python2.4" assert env.commands == [['xyz']] +class TestHashseedOption: + + def _get_envconfigs(self, newconfig, args=None, tox_ini=None, + make_hashseed=None): + if args is None: + args = [] + if tox_ini is None: + tox_ini = """ + [testenv] + """ + if make_hashseed is None: + make_hashseed = lambda: '123456789' + original_make_hashseed = tox._config.make_hashseed + tox._config.make_hashseed = make_hashseed + try: + config = newconfig(args, tox_ini) + finally: + tox._config.make_hashseed = original_make_hashseed + return config.envconfigs + + def _get_envconfig(self, newconfig, args=None, tox_ini=None): + envconfigs = self._get_envconfigs(newconfig, args=args, + tox_ini=tox_ini) + return envconfigs["python"] + + def _check_hashseed(self, envconfig, expected): + assert envconfig.setenv == {'PYTHONHASHSEED': expected} + + def _check_testenv(self, newconfig, expected, args=None, tox_ini=None): + envconfig = self._get_envconfig(newconfig, args=args, tox_ini=tox_ini) + self._check_hashseed(envconfig, expected) + + def test_default(self, tmpdir, newconfig): + self._check_testenv(newconfig, '123456789') + + def test_passing_integer(self, tmpdir, newconfig): + args = ['--hashseed', '1'] + self._check_testenv(newconfig, '1', args=args) + + def test_passing_string(self, tmpdir, newconfig): + args = ['--hashseed', 'random'] + self._check_testenv(newconfig, 'random', args=args) + + def test_passing_empty_string(self, tmpdir, newconfig): + args = ['--hashseed', ''] + self._check_testenv(newconfig, '', args=args) + + @pytest.mark.xfail(sys.version_info >= (3,2), + reason="at least Debian python 3.2/3.3 have a bug: " + "http://bugs.python.org/issue11884") + def test_passing_no_argument(self, tmpdir, newconfig): + """Test that passing no arguments to --hashseed is not allowed.""" + args = ['--hashseed'] + try: + self._check_testenv(newconfig, '', args=args) + except SystemExit: + e = sys.exc_info()[1] + assert e.code == 2 + return + assert False # getting here means we failed the test. + + def test_setenv(self, tmpdir, newconfig): + """Check that setenv takes precedence.""" + tox_ini = """ + [testenv] + setenv = + PYTHONHASHSEED = 2 + """ + self._check_testenv(newconfig, '2', tox_ini=tox_ini) + args = ['--hashseed', '1'] + self._check_testenv(newconfig, '2', args=args, tox_ini=tox_ini) + + def test_noset(self, tmpdir, newconfig): + args = ['--hashseed', 'noset'] + envconfig = self._get_envconfig(newconfig, args=args) + assert envconfig.setenv is None + + def test_noset_with_setenv(self, tmpdir, newconfig): + tox_ini = """ + [testenv] + setenv = + PYTHONHASHSEED = 2 + """ + args = ['--hashseed', 'noset'] + self._check_testenv(newconfig, '2', args=args, tox_ini=tox_ini) + + def test_one_random_hashseed(self, tmpdir, newconfig): + """Check that different testenvs use the same random seed.""" + tox_ini = """ + [testenv:hash1] + [testenv:hash2] + """ + next_seed = [1000] + # This function is guaranteed to generate a different value each time. + def make_hashseed(): + next_seed[0] += 1 + return str(next_seed[0]) + # Check that make_hashseed() works. + assert make_hashseed() == '1001' + envconfigs = self._get_envconfigs(newconfig, tox_ini=tox_ini, + make_hashseed=make_hashseed) + self._check_hashseed(envconfigs["hash1"], '1002') + # Check that hash2's value is not '1003', for example. + self._check_hashseed(envconfigs["hash2"], '1002') + + def test_setenv_in_one_testenv(self, tmpdir, newconfig): + """Check using setenv in one of multiple testenvs.""" + tox_ini = """ + [testenv:hash1] + setenv = + PYTHONHASHSEED = 2 + [testenv:hash2] + """ + envconfigs = self._get_envconfigs(newconfig, tox_ini=tox_ini) + self._check_hashseed(envconfigs["hash1"], '2') + self._check_hashseed(envconfigs["hash2"], '123456789') + class TestIndexServer: def test_indexserver(self, tmpdir, newconfig): config = newconfig(""" @@ -1000,6 +1374,29 @@ "*ERROR*tox.ini*not*found*", ]) + def test_showconfig_with_force_dep_version(self, cmd, initproj): + initproj('force_dep_version', filedefs={ + 'tox.ini': ''' + [tox] + + [testenv] + deps= + dep1==2.3 + dep2 + ''', + }) + result = cmd.run("tox", "--showconfig") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + r'*deps=*dep1==2.3, dep2*', + ]) + # override dep1 specific version, and force version for dep2 + result = cmd.run("tox", "--showconfig", "--force-dep=dep1", + "--force-dep=dep2==5.0") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + r'*deps=*dep1, dep2==5.0*', + ]) class TestArgumentParser: @@ -1077,3 +1474,13 @@ p = CommandParser(cmd) parsed = list(p.words()) assert parsed == ['nosetests', ' ', '-v', ' ', '-a', ' ', '!deferred', ' ', '--with-doctest', ' ', '[]'] + + + @pytest.mark.skipif("sys.platform != 'win32'") + def test_commands_with_backslash(self, newconfig): + config = newconfig([r"hello\world"], """ + [testenv:py26] + commands = some {posargs} + """) + envconfig = config.envconfigs["py26"] + assert envconfig.commands[0] == ["some", r"hello\world"] diff -r f6f6e21a6172a3ad3dd264746123f0660576dd69 -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf tests/test_interpreters.py --- a/tests/test_interpreters.py +++ b/tests/test_interpreters.py @@ -2,7 +2,7 @@ import os import pytest -from tox.interpreters import * +from tox.interpreters import * # noqa @pytest.fixture def interpreters(): This diff is so big that we needed to truncate the remainder. https://bitbucket.org/hpk42/tox/commits/a56d17ed9e34/ Changeset: a56d17ed9e34 Branch: echo-captured-output User: fschulze Date: 2015-02-05 13:21:44+00:00 Summary: Always tee the output to stdout when --report-json is used. Affected #: 2 files diff -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf -r a56d17ed9e345db64962bd856d521d4f92c5af65 tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -80,21 +80,20 @@ return f def popen(self, args, cwd=None, env=None, redirect=True, returnout=False): - logged_command = "%s$ %s" %(cwd, " ".join(map(str, args))) stdout = outpath = None resultjson = self.session.config.option.resultjson - resulttee = self.session.config.option.resulttee if resultjson or redirect: f = self._initlogpath(self.id) f.write("actionid=%s\nmsg=%s\ncmdargs=%r\nenv=%s\n" %( self.id, self.msg, args, env)) f.flush() self.popen_outpath = outpath = py.path.local(f.name) - stdout = f + if resultjson: + stdout = subprocess.PIPE + else: + stdout = f elif returnout: stdout = subprocess.PIPE - if resultjson and resulttee: - stdout = subprocess.PIPE if cwd is None: # XXX cwd = self.session.config.cwd cwd = py.path.local() @@ -113,15 +112,20 @@ try: self.report.logpopen(popen, env=env) try: - if resultjson and resulttee: + if resultjson and not redirect: assert popen.stderr is None # prevent deadlock out = None last_time = time.time() while 1: + # we have to read one byte at a time, otherwise there + # might be no output for a long time with slow tests data = popen.stdout.read(1) if data: sys.stdout.write(data) if '\n' in data or (time.time() - last_time) > 5: + # we flush on newlines or after 5 seconds to + # provide quick enough feedback to the user + # when printing a dot per test sys.stdout.flush() last_time = time.time() f.write(data) diff -r 8b053b6f34d40c9d31ae9ac3f95736131b5648cf -r a56d17ed9e345db64962bd856d521d4f92c5af65 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -117,9 +117,6 @@ "all commands and results involved. This will turn off " "pass-through output from running test commands which is " "instead captured into the json result file.") - parser.add_argument("--result-tee", action="store_true", - dest="resulttee", - help="echo output of --result-json to stdout while it is captured.") # We choose 1 to 4294967295 because it is the range of PYTHONHASHSEED. parser.add_argument("--hashseed", action="store", metavar="SEED", default=None, https://bitbucket.org/hpk42/tox/commits/f52220770a97/ Changeset: f52220770a97 Branch: echo-captured-output User: fschulze Date: 2015-02-05 13:24:39+00:00 Summary: Add changelog entry. Affected #: 1 file diff -r a56d17ed9e345db64962bd856d521d4f92c5af65 -r f52220770a979458e126ac7fcc5fb2acefe1ec44 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ - refine determination if we run from Jenkins, thanks Borge Lanes. +- echo output to stdout when ``--report-json`` is used 1.8.1 ----------- https://bitbucket.org/hpk42/tox/commits/27b8bdcddd6a/ Changeset: 27b8bdcddd6a User: hpk42 Date: 2015-02-09 11:13:56+00:00 Summary: Merged in fschulze/tox/echo-captured-output (pull request #132) Add ``--result-tee`` option to echo output captured for the json result to stdout. Affected #: 3 files diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ - refine determination if we run from Jenkins, thanks Borge Lanes. +- echo output to stdout when ``--report-json`` is used 1.8.1 ----------- diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -11,6 +11,7 @@ import os import sys import subprocess +import time from tox._verlib import NormalizedVersion, IrrationalVersionError from tox._venv import VirtualEnv from tox._config import parseconfig @@ -79,7 +80,7 @@ return f def popen(self, args, cwd=None, env=None, redirect=True, returnout=False): - f = outpath = None + stdout = outpath = None resultjson = self.session.config.option.resultjson if resultjson or redirect: f = self._initlogpath(self.id) @@ -87,14 +88,18 @@ self.id, self.msg, args, env)) f.flush() self.popen_outpath = outpath = py.path.local(f.name) + if resultjson: + stdout = subprocess.PIPE + else: + stdout = f elif returnout: - f = subprocess.PIPE + stdout = subprocess.PIPE if cwd is None: # XXX cwd = self.session.config.cwd cwd = py.path.local() try: popen = self._popen(args, cwd, env=env, - stdout=f, stderr=STDOUT) + stdout=stdout, stderr=STDOUT) except OSError as e: self.report.error("invocation failed (errno %d), args: %s, cwd: %s" % (e.errno, args, cwd)) @@ -107,7 +112,28 @@ try: self.report.logpopen(popen, env=env) try: - out, err = popen.communicate() + if resultjson and not redirect: + assert popen.stderr is None # prevent deadlock + out = None + last_time = time.time() + while 1: + # we have to read one byte at a time, otherwise there + # might be no output for a long time with slow tests + data = popen.stdout.read(1) + if data: + sys.stdout.write(data) + if '\n' in data or (time.time() - last_time) > 5: + # we flush on newlines or after 5 seconds to + # provide quick enough feedback to the user + # when printing a dot per test + sys.stdout.flush() + last_time = time.time() + f.write(data) + elif popen.poll() is not None: + popen.stdout.close() + break + else: + out, err = popen.communicate() except KeyboardInterrupt: self.report.keyboard_interrupt() popen.wait() Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 9 12:40:46 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 09 Feb 2015 11:40:46 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150209114046.5914.91350@app07.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/416b4d91aa91/ Changeset: 416b4d91aa91 Branch: adopt-pytest-docs User: pfctdayelise Date: 2015-02-09 10:59:15+00:00 Summary: #676 Add docs page describing 'adopt pytest month' Affected #: 3 files diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r 416b4d91aa9161e21321645c2cd650c63087ba6a doc/en/adopt.txt --- /dev/null +++ b/doc/en/adopt.txt @@ -0,0 +1,79 @@ + +April is "adopt pytest month" +============================================= + +Are you an enthusiastic pytest user, the local testing guru in your workplace? Or are you considering using pytest for your open source project, but not sure how to get started? Then you may be interested in "adopt pytest month"! + +We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest. + +In 2015 we are trying this for the first time. In February and March we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. + + +.. _`issue tracker`: https://bitbucket.org/hpk42/pytest/issue/676/adopt-pytest-month-2015 +.. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev +.. _``: + + +The ideal pytest helper +----------------------------------------- + + - will be able to commit 2-4 hours a week to working with their particular project (this might involve joining their mailing list, installing the software and exploring any existing tests, offering advice, writing some example tests) + - feels confident in using pytest (e.g. has explored command line options, knows how to write parametrized tests, has an idea about conftest contents) + - does not need to be an expert in every aspect! + +`Pytest helpers, sign up here`_! (preferably in February, hard deadline 22 March) + + +.. _`Pytest helpers, sign up here`: http://goo.gl/forms/nxqAhqWt1P + + +The ideal partner project +----------------------------------------- + + - is open source, and predominantly written in Python + - has an automated/documented install process for developers + - has more than one core developer + - has at least one official release (e.g. is available on pypi) + - has the support of the core development team, in trying out pytest adoption + - has no tests... or 100% test coverage... or somewhere in between! + +`Partner projects, sign up here`_! (by 22 March) + + +.. _`Partner projects, sign up here`: http://goo.gl/forms/ZGyqlHiwk3 + + +What does it mean to "adopt pytest"? +----------------------------------------- + +There can be many different definitions of "success". Pytest can run many `nose and unittest`_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right? + +Progressive success might look like: + + - tests can be run (by pytest) without errors (there may be failures) + - tests can be run (by pytest) without failures + - test runner is integrated into CI server + - existing tests are rewritten to take advantage of pytest features - this can happen in several iterations, for example: + - changing to native assert_ statements (pycmd_ has a script to help with that, ``pyconvert_unittest.py``) + - changing `setUp/tearDown methods`_ to fixtures_ + - adding markers_ + - other changes to reduce boilerplate + - assess needs for future tests to be written, e.g. new fixtures, distributed_ testing tweaks + +"Success" should also include that the development team feels comfortable with their knowledge of how to use pytest. In fact this is probably more important than anything else. So spending a lot of time on communication, giving examples, etc will probably be important - both in running the tests, and in writing them. + +It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies. + +.. _`nose and unittest`: faq.html#how-does-pytest-relate-to-nose-and-unittest +.. _assert: asserts.html +.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview +.. _`setUp/tearDown methods`: xunit_setup.html +.. _fixtures: fixture.html +.. _markers: markers.html +.. _distributed: xdist.html + + +Other ways to help +----------------------------------------- + +Promote! Do your favourite open source Python projects use pytest? If not, why not tell them about this page? diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r 416b4d91aa9161e21321645c2cd650c63087ba6a doc/en/contents.txt --- a/doc/en/contents.txt +++ b/doc/en/contents.txt @@ -1,10 +1,3 @@ - -.. note:: - - `improving your automated testing with pytest `_, July 25th 2014, Berlin, Germany - - `professional testing with pytest and tox `_, 24-26th November 2014, Freiburg, Germany - .. _toc: Full pytest documentation diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r 416b4d91aa9161e21321645c2cd650c63087ba6a doc/en/index.txt --- a/doc/en/index.txt +++ b/doc/en/index.txt @@ -3,7 +3,10 @@ .. note:: - next training: `professional testing with pytest and tox `_, 24-26th November 2014, Freiburg, Germany + Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? April 2015 is `adopt pytest month`_! + + +.. _`adopt pytest month`: adopt.html pytest: helps you write better programs https://bitbucket.org/hpk42/pytest/commits/a7d80ee0a5a2/ Changeset: a7d80ee0a5a2 User: hpk42 Date: 2015-02-09 11:40:41+00:00 Summary: Merged in pfctdayelise/pytest_new/adopt-pytest-docs (pull request #244) #676 Add docs page describing 'adopt pytest month' Affected #: 3 files diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 doc/en/adopt.txt --- /dev/null +++ b/doc/en/adopt.txt @@ -0,0 +1,79 @@ + +April is "adopt pytest month" +============================================= + +Are you an enthusiastic pytest user, the local testing guru in your workplace? Or are you considering using pytest for your open source project, but not sure how to get started? Then you may be interested in "adopt pytest month"! + +We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest. + +In 2015 we are trying this for the first time. In February and March we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. + + +.. _`issue tracker`: https://bitbucket.org/hpk42/pytest/issue/676/adopt-pytest-month-2015 +.. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev +.. _``: + + +The ideal pytest helper +----------------------------------------- + + - will be able to commit 2-4 hours a week to working with their particular project (this might involve joining their mailing list, installing the software and exploring any existing tests, offering advice, writing some example tests) + - feels confident in using pytest (e.g. has explored command line options, knows how to write parametrized tests, has an idea about conftest contents) + - does not need to be an expert in every aspect! + +`Pytest helpers, sign up here`_! (preferably in February, hard deadline 22 March) + + +.. _`Pytest helpers, sign up here`: http://goo.gl/forms/nxqAhqWt1P + + +The ideal partner project +----------------------------------------- + + - is open source, and predominantly written in Python + - has an automated/documented install process for developers + - has more than one core developer + - has at least one official release (e.g. is available on pypi) + - has the support of the core development team, in trying out pytest adoption + - has no tests... or 100% test coverage... or somewhere in between! + +`Partner projects, sign up here`_! (by 22 March) + + +.. _`Partner projects, sign up here`: http://goo.gl/forms/ZGyqlHiwk3 + + +What does it mean to "adopt pytest"? +----------------------------------------- + +There can be many different definitions of "success". Pytest can run many `nose and unittest`_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right? + +Progressive success might look like: + + - tests can be run (by pytest) without errors (there may be failures) + - tests can be run (by pytest) without failures + - test runner is integrated into CI server + - existing tests are rewritten to take advantage of pytest features - this can happen in several iterations, for example: + - changing to native assert_ statements (pycmd_ has a script to help with that, ``pyconvert_unittest.py``) + - changing `setUp/tearDown methods`_ to fixtures_ + - adding markers_ + - other changes to reduce boilerplate + - assess needs for future tests to be written, e.g. new fixtures, distributed_ testing tweaks + +"Success" should also include that the development team feels comfortable with their knowledge of how to use pytest. In fact this is probably more important than anything else. So spending a lot of time on communication, giving examples, etc will probably be important - both in running the tests, and in writing them. + +It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies. + +.. _`nose and unittest`: faq.html#how-does-pytest-relate-to-nose-and-unittest +.. _assert: asserts.html +.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview +.. _`setUp/tearDown methods`: xunit_setup.html +.. _fixtures: fixture.html +.. _markers: markers.html +.. _distributed: xdist.html + + +Other ways to help +----------------------------------------- + +Promote! Do your favourite open source Python projects use pytest? If not, why not tell them about this page? diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 doc/en/contents.txt --- a/doc/en/contents.txt +++ b/doc/en/contents.txt @@ -1,10 +1,3 @@ - -.. note:: - - `improving your automated testing with pytest `_, July 25th 2014, Berlin, Germany - - `professional testing with pytest and tox `_, 24-26th November 2014, Freiburg, Germany - .. _toc: Full pytest documentation diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 doc/en/index.txt --- a/doc/en/index.txt +++ b/doc/en/index.txt @@ -3,7 +3,10 @@ .. note:: - next training: `professional testing with pytest and tox `_, 24-26th November 2014, Freiburg, Germany + Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? April 2015 is `adopt pytest month`_! + + +.. _`adopt pytest month`: adopt.html pytest: helps you write better programs Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 9 12:40:47 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 09 Feb 2015 11:40:47 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: Merged in pfctdayelise/pytest_new/adopt-pytest-docs (pull request #244) Message-ID: <20150209114047.18577.94688@app07.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/a7d80ee0a5a2/ Changeset: a7d80ee0a5a2 User: hpk42 Date: 2015-02-09 11:40:41+00:00 Summary: Merged in pfctdayelise/pytest_new/adopt-pytest-docs (pull request #244) #676 Add docs page describing 'adopt pytest month' Affected #: 3 files diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 doc/en/adopt.txt --- /dev/null +++ b/doc/en/adopt.txt @@ -0,0 +1,79 @@ + +April is "adopt pytest month" +============================================= + +Are you an enthusiastic pytest user, the local testing guru in your workplace? Or are you considering using pytest for your open source project, but not sure how to get started? Then you may be interested in "adopt pytest month"! + +We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest. + +In 2015 we are trying this for the first time. In February and March we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. + + +.. _`issue tracker`: https://bitbucket.org/hpk42/pytest/issue/676/adopt-pytest-month-2015 +.. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev +.. _``: + + +The ideal pytest helper +----------------------------------------- + + - will be able to commit 2-4 hours a week to working with their particular project (this might involve joining their mailing list, installing the software and exploring any existing tests, offering advice, writing some example tests) + - feels confident in using pytest (e.g. has explored command line options, knows how to write parametrized tests, has an idea about conftest contents) + - does not need to be an expert in every aspect! + +`Pytest helpers, sign up here`_! (preferably in February, hard deadline 22 March) + + +.. _`Pytest helpers, sign up here`: http://goo.gl/forms/nxqAhqWt1P + + +The ideal partner project +----------------------------------------- + + - is open source, and predominantly written in Python + - has an automated/documented install process for developers + - has more than one core developer + - has at least one official release (e.g. is available on pypi) + - has the support of the core development team, in trying out pytest adoption + - has no tests... or 100% test coverage... or somewhere in between! + +`Partner projects, sign up here`_! (by 22 March) + + +.. _`Partner projects, sign up here`: http://goo.gl/forms/ZGyqlHiwk3 + + +What does it mean to "adopt pytest"? +----------------------------------------- + +There can be many different definitions of "success". Pytest can run many `nose and unittest`_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right? + +Progressive success might look like: + + - tests can be run (by pytest) without errors (there may be failures) + - tests can be run (by pytest) without failures + - test runner is integrated into CI server + - existing tests are rewritten to take advantage of pytest features - this can happen in several iterations, for example: + - changing to native assert_ statements (pycmd_ has a script to help with that, ``pyconvert_unittest.py``) + - changing `setUp/tearDown methods`_ to fixtures_ + - adding markers_ + - other changes to reduce boilerplate + - assess needs for future tests to be written, e.g. new fixtures, distributed_ testing tweaks + +"Success" should also include that the development team feels comfortable with their knowledge of how to use pytest. In fact this is probably more important than anything else. So spending a lot of time on communication, giving examples, etc will probably be important - both in running the tests, and in writing them. + +It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies. + +.. _`nose and unittest`: faq.html#how-does-pytest-relate-to-nose-and-unittest +.. _assert: asserts.html +.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview +.. _`setUp/tearDown methods`: xunit_setup.html +.. _fixtures: fixture.html +.. _markers: markers.html +.. _distributed: xdist.html + + +Other ways to help +----------------------------------------- + +Promote! Do your favourite open source Python projects use pytest? If not, why not tell them about this page? diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 doc/en/contents.txt --- a/doc/en/contents.txt +++ b/doc/en/contents.txt @@ -1,10 +1,3 @@ - -.. note:: - - `improving your automated testing with pytest `_, July 25th 2014, Berlin, Germany - - `professional testing with pytest and tox `_, 24-26th November 2014, Freiburg, Germany - .. _toc: Full pytest documentation diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 doc/en/index.txt --- a/doc/en/index.txt +++ b/doc/en/index.txt @@ -3,7 +3,10 @@ .. note:: - next training: `professional testing with pytest and tox `_, 24-26th November 2014, Freiburg, Germany + Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? April 2015 is `adopt pytest month`_! + + +.. _`adopt pytest month`: adopt.html pytest: helps you write better programs Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 9 17:33:43 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 09 Feb 2015 16:33:43 -0000 Subject: [Pytest-commit] commit/pytest: flub: Merged in davehunt/pytest/env-addopts (pull request #241) Message-ID: <20150209163343.22694.18789@app02.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/46d5ac0ba396/ Changeset: 46d5ac0ba396 User: flub Date: 2015-02-09 16:33:36+00:00 Summary: Merged in davehunt/pytest/env-addopts (pull request #241) Support setting configuration using the PYTEST_ADDOPTS environment variable Affected #: 5 files diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -46,3 +46,4 @@ David Mohr Nicolas Delaby Tom Viner +Dave Hunt diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ 2.7.0.dev (compared to 2.6.4) ----------------------------- +- add ability to set command line options by environment variable PYTEST_ADDOPTS. + - fix issue655: work around different ways that cause python2/3 to leak sys.exc_info into fixtures/tests causing failures in 3rd party code diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -705,6 +705,7 @@ def _preparse(self, args, addopts=True): self._initini(args) if addopts: + args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args args[:] = self.getini("addopts") + args self._checkversion() self.pluginmanager.consider_preparse(args) diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 doc/en/customize.txt --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -60,6 +60,11 @@ [pytest] addopts = -rsxX -q +Alternatively, you can set a PYTEST_ADDOPTS environment variable to add command +line options while the environment is in use:: + + export PYTEST_ADDOPTS="-rsxX -q" + From now on, running ``pytest`` will add the specified options. Builtin configuration file options diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -18,12 +18,16 @@ def test_getcfg_empty_path(self, tmpdir): getcfg([''], ['setup.cfg']) #happens on py.test "" - def test_append_parse_args(self, testdir, tmpdir): + def test_append_parse_args(self, testdir, tmpdir, monkeypatch): + monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"') tmpdir.join("setup.cfg").write(py.code.Source(""" [pytest] addopts = --verbose """)) config = testdir.parseconfig(tmpdir) + assert config.option.color == 'no' + assert config.option.reportchars == 's' + assert config.option.tbstyle == 'short' assert config.option.verbose #config = testdir.Config() #args = [tmpdir,] Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 9 17:33:42 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 09 Feb 2015 16:33:42 -0000 Subject: [Pytest-commit] commit/pytest: 5 new changesets Message-ID: <20150209163342.25737.9674@app09.ash-private.bitbucket.org> 5 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/c6f91e74a2a2/ Changeset: c6f91e74a2a2 Branch: env-addopts User: Dave Hunt Date: 2015-01-23 20:09:42+00:00 Summary: Support setting configuration using the PYTEST_ADDOPTS environment variable. Affected #: 2 files diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r c6f91e74a2a22161f616f604a8fa41684ecfedb8 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -705,6 +705,8 @@ def _preparse(self, args, addopts=True): self._initini(args) if addopts: + env_addopts = os.environ.get('PYTEST_ADDOPTS', '') + args[:] = env_addopts.replace('"', '').split() + args args[:] = self.getini("addopts") + args self._checkversion() self.pluginmanager.consider_preparse(args) diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r c6f91e74a2a22161f616f604a8fa41684ecfedb8 testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,3 +1,5 @@ +import os + import py, pytest from _pytest.config import getcfg @@ -19,11 +21,16 @@ getcfg([''], ['setup.cfg']) #happens on py.test "" def test_append_parse_args(self, testdir, tmpdir): + os.environ['PYTEST_ADDOPTS'] = '--color no -rs --tb="short"' tmpdir.join("setup.cfg").write(py.code.Source(""" [pytest] addopts = --verbose """)) config = testdir.parseconfig(tmpdir) + del os.environ['PYTEST_ADDOPTS'] + assert config.option.color == 'no' + assert config.option.reportchars == 's' + assert config.option.tbstyle == 'short' assert config.option.verbose #config = testdir.Config() #args = [tmpdir,] https://bitbucket.org/hpk42/pytest/commits/2d4fcdd3609d/ Changeset: 2d4fcdd3609d Branch: env-addopts User: Dave Hunt Date: 2015-01-26 10:39:21+00:00 Summary: Use shlex to split the arguments from PYTEST_ADDOPTS. Affected #: 1 file diff -r c6f91e74a2a22161f616f604a8fa41684ecfedb8 -r 2d4fcdd3609d648d6eef5d0741b305c0ac2b4cee _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -705,8 +705,7 @@ def _preparse(self, args, addopts=True): self._initini(args) if addopts: - env_addopts = os.environ.get('PYTEST_ADDOPTS', '') - args[:] = env_addopts.replace('"', '').split() + args + args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args args[:] = self.getini("addopts") + args self._checkversion() self.pluginmanager.consider_preparse(args) https://bitbucket.org/hpk42/pytest/commits/e98f9c9e703e/ Changeset: e98f9c9e703e Branch: env-addopts User: Dave Hunt Date: 2015-01-29 10:52:01+00:00 Summary: Use monkeypatch to set the PYTEST_ADDOPTS environment variable in the test. Affected #: 1 file diff -r 2d4fcdd3609d648d6eef5d0741b305c0ac2b4cee -r e98f9c9e703ead8a39feaa2b2ace0e892d293bfd testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,5 +1,3 @@ -import os - import py, pytest from _pytest.config import getcfg @@ -20,14 +18,13 @@ def test_getcfg_empty_path(self, tmpdir): getcfg([''], ['setup.cfg']) #happens on py.test "" - def test_append_parse_args(self, testdir, tmpdir): - os.environ['PYTEST_ADDOPTS'] = '--color no -rs --tb="short"' + def test_append_parse_args(self, testdir, tmpdir, monkeypatch): + monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"') tmpdir.join("setup.cfg").write(py.code.Source(""" [pytest] addopts = --verbose """)) config = testdir.parseconfig(tmpdir) - del os.environ['PYTEST_ADDOPTS'] assert config.option.color == 'no' assert config.option.reportchars == 's' assert config.option.tbstyle == 'short' https://bitbucket.org/hpk42/pytest/commits/71fc066403d2/ Changeset: 71fc066403d2 Branch: env-addopts User: Dave Hunt Date: 2015-02-09 14:11:54+00:00 Summary: Added documentation for PYTEST_ADDOPTS environment variable, updated CHANGELOG and AUTHORS. Affected #: 3 files diff -r e98f9c9e703ead8a39feaa2b2ace0e892d293bfd -r 71fc066403d29c44ae087a4c9988370b162e2167 AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -46,3 +46,4 @@ David Mohr Nicolas Delaby Tom Viner +Dave Hunt diff -r e98f9c9e703ead8a39feaa2b2ace0e892d293bfd -r 71fc066403d29c44ae087a4c9988370b162e2167 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ 2.7.0.dev (compared to 2.6.4) ----------------------------- +- add ability to set command line options by environment variable PYTEST_ADDOPTS. + - fix issue655: work around different ways that cause python2/3 to leak sys.exc_info into fixtures/tests causing failures in 3rd party code diff -r e98f9c9e703ead8a39feaa2b2ace0e892d293bfd -r 71fc066403d29c44ae087a4c9988370b162e2167 doc/en/customize.txt --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -60,6 +60,11 @@ [pytest] addopts = -rsxX -q +Alternatively, you can set a PYTEST_ADDOPTS environment variable to add command +line options while the environment is in use:: + + export PYTEST_ADDOPTS="-rsxX -q" + From now on, running ``pytest`` will add the specified options. Builtin configuration file options https://bitbucket.org/hpk42/pytest/commits/46d5ac0ba396/ Changeset: 46d5ac0ba396 User: flub Date: 2015-02-09 16:33:36+00:00 Summary: Merged in davehunt/pytest/env-addopts (pull request #241) Support setting configuration using the PYTEST_ADDOPTS environment variable Affected #: 5 files diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -46,3 +46,4 @@ David Mohr Nicolas Delaby Tom Viner +Dave Hunt diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ 2.7.0.dev (compared to 2.6.4) ----------------------------- +- add ability to set command line options by environment variable PYTEST_ADDOPTS. + - fix issue655: work around different ways that cause python2/3 to leak sys.exc_info into fixtures/tests causing failures in 3rd party code diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -705,6 +705,7 @@ def _preparse(self, args, addopts=True): self._initini(args) if addopts: + args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args args[:] = self.getini("addopts") + args self._checkversion() self.pluginmanager.consider_preparse(args) diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 doc/en/customize.txt --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -60,6 +60,11 @@ [pytest] addopts = -rsxX -q +Alternatively, you can set a PYTEST_ADDOPTS environment variable to add command +line options while the environment is in use:: + + export PYTEST_ADDOPTS="-rsxX -q" + From now on, running ``pytest`` will add the specified options. Builtin configuration file options diff -r a7d80ee0a5a24bd0c9f9d3b3997f0a7f5bc10189 -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -18,12 +18,16 @@ def test_getcfg_empty_path(self, tmpdir): getcfg([''], ['setup.cfg']) #happens on py.test "" - def test_append_parse_args(self, testdir, tmpdir): + def test_append_parse_args(self, testdir, tmpdir, monkeypatch): + monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"') tmpdir.join("setup.cfg").write(py.code.Source(""" [pytest] addopts = --verbose """)) config = testdir.parseconfig(tmpdir) + assert config.option.color == 'no' + assert config.option.reportchars == 's' + assert config.option.tbstyle == 'short' assert config.option.verbose #config = testdir.Config() #args = [tmpdir,] Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From issues-reply at bitbucket.org Tue Feb 10 06:15:56 2015 From: issues-reply at bitbucket.org (Roman Bolshakov) Date: Tue, 10 Feb 2015 05:15:56 -0000 Subject: [Pytest-commit] Issue #678: pytest cannot deal with utf-8 encoded __repr__ of a custom object (hpk42/pytest) Message-ID: <20150210051556.17175.71060@app08.ash-private.bitbucket.org> New issue 678: pytest cannot deal with utf-8 encoded __repr__ of a custom object https://bitbucket.org/hpk42/pytest/issue/678/pytest-cannot-deal-with-utf-8-encoded Roman Bolshakov: I have a test module which does use beautiful soup to parse some test data. I added an assertion to check that a variable I assigned result of parsing to is an instance of unicode type. I had a bug in my code, a list with various objects got returned instead of the expected unicode string, the assertion fired. Besides, I got a totally unexpected UnicodeDecodeError in pytest. Here's how it could be reproduced: https://gist.github.com/roolebo/ca816a26cdc0a8b17226 It turned out that beautiful soup returns utf-8 encoded string as a result of __repr__ invocation on Tag object. The gist above could be nailed down without beautiful soup dependency: ``` #!python # coding=utf-8 def test_unicode_repr(): class Foo(object): a = 1 def __repr__(self): return '?' f = Foo() assert 0 == f.a ``` ``` #!python lines = ['assert 0 == 1', '{1 = \xd0.a', '}'] def _format_lines(lines): """Format the individual lines This will replace the '{', '}' and '~' characters of our mini formatting language with the proper 'where ...', 'and ...' and ' + ...' text, taking care of indentation along the way. Return a list of formatted lines. """ result = lines[:1] stack = [0] stackcnt = [0] for line in lines[1:]: if line.startswith('{'): if stackcnt[-1]: s = u('and ') else: s = u('where ') stack.append(len(result)) stackcnt[-1] += 1 stackcnt.append(0) > result.append(u(' +') + u(' ')*(len(stack)-1) + s + line[1:]) E UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 23: ordinal not in range(128) ../venv/lib/python2.7/site-packages/_pytest/assertion/util.py:104: UnicodeDecodeError ``` From issues-reply at bitbucket.org Tue Feb 10 22:11:21 2015 From: issues-reply at bitbucket.org (Diego Ponciano) Date: Tue, 10 Feb 2015 21:11:21 -0000 Subject: [Pytest-commit] Issue #679: option to make looponfail ignore certain files (hpk42/pytest) Message-ID: <20150210211121.1605.58036@app02.ash-private.bitbucket.org> New issue 679: option to make looponfail ignore certain files https://bitbucket.org/hpk42/pytest/issue/679/option-to-make-looponfail-ignore-certain Diego Ponciano: I'm running py.test with -f (looponfail) from the project dir, and my model tests recreate a sqlite database at every run. The problem that comes with it is that py.test detects the database.db file was changed, and then re-run all the tests infinitely. Is there a way to make it ignore changes in *.db files? From commits-noreply at bitbucket.org Wed Feb 11 00:33:53 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Tue, 10 Feb 2015 23:33:53 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: addresses #16 - replace Generator with pytest_pyfunc_interpret_result Message-ID: <20150210233353.8926.97524@app07.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/bd9f28f011ea/ Changeset: bd9f28f011ea Branch: yield-test-run-inline User: RonnyPfannschmidt Date: 2015-02-10 23:33:18+00:00 Summary: addresses #16 - replace Generator with pytest_pyfunc_interpret_result Affected #: 10 files diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,16 @@ 2.7.0.dev (compared to 2.6.4) ----------------------------- +- introduce the hook pytest_pyfunc_interpret_result + this eases interpreting test functions results like generators, + twisted inline defereds, futures and asyncio generators + +- replace the Generator concept with the pytest_pyfunc_interpret_result hook + (Note: this change reduces reporting detail for generator tests, + that will be addressed in a later release) + + the Generator class is now a alias to Function + - add ability to set command line options by environment variable PYTEST_ADDOPTS. - fix issue655: work around different ways that cause python2/3 diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f _pytest/hookspec.py --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -136,6 +136,10 @@ """ call underlying test function. """ pytest_pyfunc_call.firstresult = True + +def pytest_pyfunc_interpret_result(pyfuncitem, result): + """ interpret the return value of the underlying test function. """ + def pytest_generate_tests(metafunc): """ generate (multiple) parametrized calls to a test function.""" diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f _pytest/nose.py --- a/_pytest/nose.py +++ b/_pytest/nose.py @@ -27,13 +27,6 @@ @pytest.mark.trylast def pytest_runtest_setup(item): if is_potential_nosetest(item): - if isinstance(item.parent, pytest.Generator): - gen = item.parent - if not hasattr(gen, '_nosegensetup'): - call_optional(gen.obj, 'setup') - if isinstance(gen.parent, pytest.Instance): - call_optional(gen.parent.obj, 'setup') - gen._nosegensetup = True if not call_optional(item.obj, 'setup'): # call module level setup if there is no object level one call_optional(item.parent.obj, 'setup') @@ -49,11 +42,6 @@ # del item.parent._nosegensetup -def pytest_make_collect_report(collector): - if isinstance(collector, pytest.Generator): - call_optional(collector.obj, 'setup') - - def is_potential_nosetest(item): # extra check needed since we do not do nose style setup/teardown # on direct unittest style classes diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -177,7 +177,9 @@ 'raises' : raises, 'collect': { 'Module': Module, 'Class': Class, 'Instance': Instance, - 'Function': Function, 'Generator': Generator, + 'Function': Function, + # TODO: backward compatibility check + 'Generator': Function, '_fillfuncargs': fillfixtures} } @@ -188,16 +190,38 @@ @pytest.mark.trylast +def pytest_pyfunc_interpret_result(pyfuncitem, result): + if inspect.isgenerator(result): + pyfuncitem.warn( + code='G01', + message='generator test, reporting is limited') + for check in result: + # TODO(ronny): subtest support needed + if callable(check): + check() + elif not isinstance(check, tuple): + pytest.fail('%r is not a check' % (check,)) + elif callable(check[0]): + check[0](*check[1:]) + elif callable(check[1]): + check[1](*check[2:]) + else: + pytest.fail( + 'generator test check not callable \n%r' % (check,)) + + + at pytest.mark.trylast def pytest_pyfunc_call(pyfuncitem): testfunction = pyfuncitem.obj - if pyfuncitem._isyieldedfunction(): - testfunction(*pyfuncitem._args) - else: - funcargs = pyfuncitem.funcargs - testargs = {} - for arg in pyfuncitem._fixtureinfo.argnames: - testargs[arg] = funcargs[arg] - testfunction(**testargs) + funcargs = pyfuncitem.funcargs + testargs = {} + for arg in pyfuncitem._fixtureinfo.argnames: + testargs[arg] = funcargs[arg] + result = testfunction(**testargs) + if result is not None: + pyfuncitem.ihook.pytest_pyfunc_interpret_result( + pyfuncitem=pyfuncitem, + result=result) return True def pytest_collect_file(path, parent): @@ -235,10 +259,7 @@ "cannot collect %r because it is not a function." % name, ) if getattr(obj, "__test__", True): - if is_generator(obj): - res = Generator(name, parent=collector) - else: - res = list(collector._genfunctions(name, obj)) + res = list(collector._genfunctions(name, obj)) outcome.force_result(res) def is_generator(func): @@ -621,43 +642,6 @@ return self._repr_failure_py(excinfo, style=style) -class Generator(FunctionMixin, PyCollector): - def collect(self): - # test generators are seen as collectors but they also - # invoke setup/teardown on popular request - # (induced by the common "test_*" naming shared with normal tests) - self.session._setupstate.prepare(self) - # see FunctionMixin.setup and test_setupstate_is_preserved_134 - self._preservedparent = self.parent.obj - l = [] - seen = {} - 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,)) - 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)) - seen[name] = True - l.append(self.Function(name, self, args=args, callobj=call)) - return l - - def getcallargs(self, obj): - if not isinstance(obj, (tuple, list)): - obj = (obj,) - # explict naming - if isinstance(obj[0], py.builtin._basestring): - name = obj[0] - obj = obj[1:] - else: - name = None - call, args = obj[0], obj[1:] - return name, call, args - - def hasinit(obj): init = getattr(obj, '__init__', None) if init: diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f testing/python/collect.py --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -76,199 +76,6 @@ ]) -class TestGenerator: - def test_generative_functions(self, testdir): - modcol = testdir.getmodulecol(""" - def func1(arg, arg2): - assert arg == arg2 - - def test_gen(): - yield func1, 17, 3*5 - yield func1, 42, 6*7 - """) - colitems = modcol.collect() - assert len(colitems) == 1 - gencol = colitems[0] - assert isinstance(gencol, pytest.Generator) - gencolitems = gencol.collect() - assert len(gencolitems) == 2 - assert isinstance(gencolitems[0], pytest.Function) - assert isinstance(gencolitems[1], pytest.Function) - assert gencolitems[0].name == '[0]' - assert gencolitems[0].obj.__name__ == 'func1' - - def test_generative_methods(self, testdir): - modcol = testdir.getmodulecol(""" - def func1(arg, arg2): - assert arg == arg2 - class TestGenMethods: - def test_gen(self): - yield func1, 17, 3*5 - yield func1, 42, 6*7 - """) - gencol = modcol.collect()[0].collect()[0].collect()[0] - assert isinstance(gencol, pytest.Generator) - gencolitems = gencol.collect() - assert len(gencolitems) == 2 - assert isinstance(gencolitems[0], pytest.Function) - assert isinstance(gencolitems[1], pytest.Function) - assert gencolitems[0].name == '[0]' - assert gencolitems[0].obj.__name__ == 'func1' - - def test_generative_functions_with_explicit_names(self, testdir): - modcol = testdir.getmodulecol(""" - def func1(arg, arg2): - assert arg == arg2 - - def test_gen(): - yield "seventeen", func1, 17, 3*5 - yield "fortytwo", func1, 42, 6*7 - """) - colitems = modcol.collect() - assert len(colitems) == 1 - gencol = colitems[0] - assert isinstance(gencol, pytest.Generator) - gencolitems = gencol.collect() - assert len(gencolitems) == 2 - assert isinstance(gencolitems[0], pytest.Function) - assert isinstance(gencolitems[1], pytest.Function) - assert gencolitems[0].name == "['seventeen']" - assert gencolitems[0].obj.__name__ == 'func1' - assert gencolitems[1].name == "['fortytwo']" - assert gencolitems[1].obj.__name__ == 'func1' - - def test_generative_functions_unique_explicit_names(self, testdir): - # generative - modcol = testdir.getmodulecol(""" - def func(): pass - def test_gen(): - yield "name", func - yield "name", func - """) - colitems = modcol.collect() - assert len(colitems) == 1 - gencol = colitems[0] - assert isinstance(gencol, pytest.Generator) - pytest.raises(ValueError, "gencol.collect()") - - def test_generative_methods_with_explicit_names(self, testdir): - modcol = testdir.getmodulecol(""" - def func1(arg, arg2): - assert arg == arg2 - class TestGenMethods: - def test_gen(self): - yield "m1", func1, 17, 3*5 - yield "m2", func1, 42, 6*7 - """) - gencol = modcol.collect()[0].collect()[0].collect()[0] - assert isinstance(gencol, pytest.Generator) - gencolitems = gencol.collect() - assert len(gencolitems) == 2 - assert isinstance(gencolitems[0], pytest.Function) - assert isinstance(gencolitems[1], pytest.Function) - assert gencolitems[0].name == "['m1']" - assert gencolitems[0].obj.__name__ == 'func1' - assert gencolitems[1].name == "['m2']" - assert gencolitems[1].obj.__name__ == 'func1' - - def test_order_of_execution_generator_same_codeline(self, testdir, tmpdir): - o = testdir.makepyfile(""" - def test_generative_order_of_execution(): - import py, pytest - test_list = [] - expected_list = list(range(6)) - - def list_append(item): - test_list.append(item) - - def assert_order_of_execution(): - py.builtin.print_('expected order', expected_list) - py.builtin.print_('but got ', test_list) - assert test_list == expected_list - - for i in expected_list: - yield list_append, i - yield assert_order_of_execution - """) - reprec = testdir.inline_run(o) - passed, skipped, failed = reprec.countoutcomes() - assert passed == 7 - assert not skipped and not failed - - def test_order_of_execution_generator_different_codeline(self, testdir): - o = testdir.makepyfile(""" - def test_generative_tests_different_codeline(): - import py, pytest - test_list = [] - expected_list = list(range(3)) - - def list_append_2(): - test_list.append(2) - - def list_append_1(): - test_list.append(1) - - def list_append_0(): - test_list.append(0) - - def assert_order_of_execution(): - py.builtin.print_('expected order', expected_list) - py.builtin.print_('but got ', test_list) - assert test_list == expected_list - - yield list_append_0 - yield list_append_1 - yield list_append_2 - yield assert_order_of_execution - """) - reprec = testdir.inline_run(o) - passed, skipped, failed = reprec.countoutcomes() - assert passed == 4 - assert not skipped and not failed - - def test_setupstate_is_preserved_134(self, testdir): - # yield-based tests are messy wrt to setupstate because - # during collection they already invoke setup functions - # and then again when they are run. For now, we want to make sure - # that the old 1.3.4 behaviour is preserved such that all - # yielded functions all share the same "self" instance that - # has been used during collection. - o = testdir.makepyfile(""" - setuplist = [] - class TestClass: - def setup_method(self, func): - #print "setup_method", self, func - setuplist.append(self) - self.init = 42 - - def teardown_method(self, func): - self.init = None - - def test_func1(self): - pass - - def test_func2(self): - yield self.func2 - yield self.func2 - - def func2(self): - assert self.init - - def test_setuplist(): - # once for test_func2 during collection - # once for test_func1 during test run - # once for test_func2 during test run - #print setuplist - assert len(setuplist) == 3, len(setuplist) - assert setuplist[0] == setuplist[2], setuplist - assert setuplist[1] != setuplist[2], setuplist - """) - reprec = testdir.inline_run(o, '-v') - passed, skipped, failed = reprec.countoutcomes() - assert passed == 4 - assert not skipped and not failed - - class TestFunction: def test_getmodulecollector(self, testdir): item = testdir.getitem("def test_func(): pass") @@ -690,37 +497,6 @@ assert lineno == 1 assert msg == "TestClass" - def test_generator_reportinfo(self, testdir): - modcol = testdir.getmodulecol(""" - # lineno 0 - def test_gen(): - def check(x): - assert x - yield check, 3 - """) - gencol = testdir.collect_by_name(modcol, "test_gen") - fspath, lineno, modpath = gencol.reportinfo() - assert fspath == modcol.fspath - assert lineno == 1 - assert modpath == "test_gen" - - genitem = gencol.collect()[0] - fspath, lineno, modpath = genitem.reportinfo() - assert fspath == modcol.fspath - assert lineno == 2 - assert modpath == "test_gen[0]" - """ - def test_func(): - pass - def test_genfunc(): - def check(x): - pass - yield check, 3 - class TestClass: - def test_method(self): - pass - """ - def test_customized_python_discovery(testdir): testdir.makeini(""" diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f testing/python/fixture.py --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -1246,9 +1246,7 @@ yield f, -3 """) reprec = testdir.inline_run() - reprec.assertoutcome(passed=2) - - + reprec.assertoutcome(passed=1) def test_funcarg_and_setup(self, testdir): testdir.makepyfile(""" diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f testing/test_nose.py --- a/testing/test_nose.py +++ b/testing/test_nose.py @@ -146,6 +146,7 @@ ]) + at pytest.mark.xfail(reason='generator tests dont hook into setup/teardown') def test_nose_test_generator_fixtures(testdir): p = testdir.makepyfile(""" # taken from nose-0.11.1 unit_tests/test_generator_fixtures.py diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f testing/test_runner_xunit.py --- a/testing/test_runner_xunit.py +++ b/testing/test_runner_xunit.py @@ -1,6 +1,7 @@ # # test correct setup/teardowns at # module, class, and instance level +import pytest def test_module_and_function_setup(testdir): reprec = testdir.inline_runsource(""" @@ -141,6 +142,8 @@ """) reprec.assertoutcome(failed=1, passed=1) + + at pytest.mark.xfail(reason='generator check reporting detail got reduced') def test_method_generator_setup(testdir): reprec = testdir.inline_runsource(""" class TestSetupTeardownOnInstance: diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f testing/test_session.py --- a/testing/test_session.py +++ b/testing/test_session.py @@ -61,9 +61,10 @@ def test_1(): yield None """) - failures = reprec.getfailedcollections() - out = failures[0].longrepr.reprcrash.message - i = out.find('TypeError') + passed, skipped, failed = reprec.listoutcomes() + assert len(failed) == 1 + out = failed[0].longrepr.reprcrash.message + i = out.find('not a check') assert i != -1 def test_syntax_error_module(self, testdir): diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f testing/test_terminal.py --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -453,7 +453,7 @@ "*test_verbose_reporting.py::test_fail *FAIL*", "*test_verbose_reporting.py::test_pass *PASS*", "*test_verbose_reporting.py::TestClass::test_skip *SKIP*", - "*test_verbose_reporting.py::test_gen*0* *FAIL*", + "*test_verbose_reporting.py::test_gen *FAIL*", ]) assert result.ret == 1 Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Wed Feb 11 00:53:45 2015 From: builds at drone.io (Drone.io Build) Date: Tue, 10 Feb 2015 23:53:45 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 368 Message-ID: <20150210234321.29520.14284@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/368 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3848:bd9f28f011ea Author : Ronny Pfannschmidt Branch : yield-test-run-inline Message: addresses #16 - replace Generator with pytest_pyfunc_interpret_result -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Wed Feb 11 01:07:30 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 11 Feb 2015 00:07:30 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: small refactoring of yield test interpretation Message-ID: <20150211000730.15371.40134@app13.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/e507c61f1fc0/ Changeset: e507c61f1fc0 Branch: yield-test-run-inline User: RonnyPfannschmidt Date: 2015-02-11 00:06:55+00:00 Summary: small refactoring of yield test interpretation Affected #: 1 file diff -r bd9f28f011eafe48ddf95b6a3e9dd260aa69c99f -r e507c61f1fc036a902cfcc3003d2d8b074273d06 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -189,26 +189,35 @@ return request.config + +def _get_check_nameargs(obj, idx): + if not isinstance(obj, (list, tuple)): + obj = (obj,) + # explict naming + + if isinstance(obj[0], py.builtin._basestring): + name = '[%s]' % obj[0] + obj = obj[1:] + else: + name = '[%d]' % idx + call, args = obj[0], obj[1:] + if not callable(call): + pytest.fail('not a check\n' + 'name=%s call=%r args=%r' % (name, call, args)) + return name, call, args + + + @pytest.mark.trylast def pytest_pyfunc_interpret_result(pyfuncitem, result): if inspect.isgenerator(result): pyfuncitem.warn( code='G01', message='generator test, reporting is limited') - for check in result: + for idx, check in enumerate(result): # TODO(ronny): subtest support needed - if callable(check): - check() - elif not isinstance(check, tuple): - pytest.fail('%r is not a check' % (check,)) - elif callable(check[0]): - check[0](*check[1:]) - elif callable(check[1]): - check[1](*check[2:]) - else: - pytest.fail( - 'generator test check not callable \n%r' % (check,)) - + name, call, args = _get_check_nameargs(check, idx) + call(*args) @pytest.mark.trylast def pytest_pyfunc_call(pyfuncitem): Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Wed Feb 11 01:17:23 2015 From: builds at drone.io (Drone.io Build) Date: Wed, 11 Feb 2015 00:17:23 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 369 Message-ID: <20150211001721.37937.81274@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/369 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3849:e507c61f1fc0 Author : Ronny Pfannschmidt Branch : yield-test-run-inline Message: small refactoring of yield test interpretation -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Wed Feb 11 14:40:05 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 11 Feb 2015 13:40:05 -0000 Subject: [Pytest-commit] commit/tox: hpk42: Merged in juliankrause/tox (pull request #131) Message-ID: <20150211134005.9951.12524@app10.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/c620462d578e/ Changeset: c620462d578e User: hpk42 Date: 2015-02-11 13:39:59+00:00 Summary: Merged in juliankrause/tox (pull request #131) Fix issue11: Add a skip_install option on a per-environment level. Affected #: 3 files diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -252,6 +252,16 @@ **default**: ``False`` +.. confval:: skip_install=BOOL + + .. versionadded:: 1.9 + + Do not install the current package. This can be used when you need the + virtualenv management but do not want to install the current package + into that environment. + + **default**: ``False`` + Substitutions ------------- diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -474,7 +474,7 @@ if self.setupenv(venv): if venv.envconfig.develop: self.developpkg(venv, self.config.setupdir) - elif self.config.skipsdist: + elif self.config.skipsdist or venv.envconfig.skip_install: self.finishvenv(venv) else: self.installpkg(venv, sdist_path) diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -395,6 +395,8 @@ vc.pip_pre = config.option.pre or reader.getbool( section, "pip_pre", False) + vc.skip_install = reader.getbool(section, "skip_install", False) + return vc def _getenvdata(self, reader, toxsection): Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Wed Feb 11 14:40:04 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 11 Feb 2015 13:40:04 -0000 Subject: [Pytest-commit] commit/tox: 2 new changesets Message-ID: <20150211134004.26931.97542@app05.ash-private.bitbucket.org> 2 new commits in tox: https://bitbucket.org/hpk42/tox/commits/dbcf84d3406d/ Changeset: dbcf84d3406d User: juliankrause Date: 2015-01-22 22:52:53+00:00 Summary: Fix issue11: Add a skip_install option on a per-environment level. Affected #: 3 files diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r dbcf84d3406df64ed03ec93b7dc923b251007a0d doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -252,6 +252,16 @@ **default**: ``False`` +.. confval:: skip_install=BOOL + + .. versionadded:: 1.9 + + Do not install the current package. This can be used when you need the + virtualenv management but do not want to install the current package + into that environment. + + **default**: ``False`` + Substitutions ------------- diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r dbcf84d3406df64ed03ec93b7dc923b251007a0d tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -448,7 +448,7 @@ if self.setupenv(venv): if venv.envconfig.develop: self.developpkg(venv, self.config.setupdir) - elif self.config.skipsdist: + elif self.config.skipsdist or venv.envconfig.skip_install: self.finishvenv(venv) else: self.installpkg(venv, sdist_path) diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r dbcf84d3406df64ed03ec93b7dc923b251007a0d tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -395,6 +395,8 @@ vc.pip_pre = config.option.pre or reader.getbool( section, "pip_pre", False) + vc.skip_install = reader.getbool(section, "skip_install", False) + return vc def _getenvdata(self, reader, toxsection): https://bitbucket.org/hpk42/tox/commits/c620462d578e/ Changeset: c620462d578e User: hpk42 Date: 2015-02-11 13:39:59+00:00 Summary: Merged in juliankrause/tox (pull request #131) Fix issue11: Add a skip_install option on a per-environment level. Affected #: 3 files diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -252,6 +252,16 @@ **default**: ``False`` +.. confval:: skip_install=BOOL + + .. versionadded:: 1.9 + + Do not install the current package. This can be used when you need the + virtualenv management but do not want to install the current package + into that environment. + + **default**: ``False`` + Substitutions ------------- diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -474,7 +474,7 @@ if self.setupenv(venv): if venv.envconfig.develop: self.developpkg(venv, self.config.setupdir) - elif self.config.skipsdist: + elif self.config.skipsdist or venv.envconfig.skip_install: self.finishvenv(venv) else: self.installpkg(venv, sdist_path) diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -395,6 +395,8 @@ vc.pip_pre = config.option.pre or reader.getbool( section, "pip_pre", False) + vc.skip_install = reader.getbool(section, "skip_install", False) + return vc def _getenvdata(self, reader, toxsection): Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Wed Feb 11 14:41:49 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Wed, 11 Feb 2015 13:41:49 -0000 Subject: [Pytest-commit] commit/tox: hpk42: fix issue11: add a ``skip_install`` per-testenv setting which Message-ID: <20150211134149.760.69615@app01.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/e2be096eb1c1/ Changeset: e2be096eb1c1 User: hpk42 Date: 2015-02-11 13:41:32+00:00 Summary: fix issue11: add a ``skip_install`` per-testenv setting which prevents the installation of a package. Thanks Julian Krause. Affected #: 2 files diff -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,9 @@ - echo output to stdout when ``--report-json`` is used +- fix issue11: add a ``skip_install`` per-testenv setting which + prevents the installation of a package. Thanks Julian Krause. + 1.8.1 ----------- diff -r c620462d578e3c73e33bbbcbe8aa90005edf48d1 -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -24,6 +24,7 @@ Mattieu Agopian Asmund Grammeltwedt Ionel Maries Cristian +Julian Krause Alexandre Conrad Morgan Fainberg Marc Schlaich Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Thu Feb 12 10:32:37 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 12 Feb 2015 09:32:37 -0000 Subject: [Pytest-commit] commit/pytest: 3 new changesets Message-ID: <20150212093237.25024.51225@app05.ash-private.bitbucket.org> 3 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/fbad7df469fd/ Changeset: fbad7df469fd Branch: jeffwidman/fix-faq-grammar-and-spelling-1423641159173 User: jeffwidman Date: 2015-02-11 07:52:48+00:00 Summary: Fix: FAQ grammar and spelling Affected #: 1 file diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r fbad7df469fd22f8f64367240983e5ecea92096f doc/en/faq.txt --- a/doc/en/faq.txt +++ b/doc/en/faq.txt @@ -30,15 +30,15 @@ If you are using trial's unittest.TestCase chances are that you can just run your tests even if you return Deferreds. In addition, there also is a dedicated `pytest-twisted -`_ plugin which allows to -return deferreds from pytest-style tests, allowing to use +`_ plugin which allows you to +return deferreds from pytest-style tests, allowing the use of :ref:`fixtures` and other features. how does pytest work with Django? ++++++++++++++++++++++++++++++++++++++++++++++ In 2012, some work is going into the `pytest-django plugin `_. It substitutes the usage of Django's -``manage.py test`` and allows to use all pytest features_ most of which +``manage.py test`` and allows the use of all pytest features_ most of which are not available from Django directly. .. _features: features.html @@ -49,7 +49,7 @@ Around 2007 (version ``0.8``) some people thought that ``pytest`` was using too much "magic". It had been part of the `pylib`_ which -contains a lot of unreleated python library code. Around 2010 there +contains a lot of unrelated python library code. Around 2010 there was a major cleanup refactoring, which removed unused or deprecated code and resulted in the new ``pytest`` PyPI package which strictly contains only test-related code. This release also brought a complete pluginification @@ -63,7 +63,7 @@ Nowadays, ``pytest`` explicitely rewrites assert statements in test modules in order to provide more useful :ref:`assert feedback `. This completely avoids previous issues of confusing assertion-reporting. -It also means, that you can use Python's ``-O`` optimization without loosing +It also means, that you can use Python's ``-O`` optimization without losing assertions in test modules. ``pytest`` contains a second, mostly obsolete, assert debugging technique, @@ -105,7 +105,7 @@ For simple applications and for people experienced with nose_ or unittest-style test setup using `xUnit style setup`_ probably -feels natural. For larger test suites, parametrized testing +feels natural. For larger test suites, parameterized testing or setup of complex test resources using funcargs_ may feel more natural. Moreover, funcargs are ideal for writing advanced test support code (like e.g. the monkeypatch_, the tmpdir_ or capture_ funcargs) @@ -152,13 +152,13 @@ Issues with pytest, multiprocess and setuptools? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -On windows the multiprocess package will instantiate sub processes +On Windows the multiprocess package will instantiate sub processes by pickling and thus implicitly re-import a lot of local modules. Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'`` protect its generated command line script. This leads to infinite recursion when running a test that instantiates Processes. -As of middle 2013, there shouldn't be a problem anymore when you +As of mid-2013, there shouldn't be a problem anymore when you use the standard setuptools (note that distribute has been merged back into setuptools which is now shipped directly with virtualenv). https://bitbucket.org/hpk42/pytest/commits/d91185b2447f/ Changeset: d91185b2447f Branch: jeffwidman/fix-faq-grammar-and-spelling-1423641159173 User: jeffwidman Date: 2015-02-11 19:27:51+00:00 Summary: Changed back to "parametrized" to match the API Affected #: 1 file diff -r fbad7df469fd22f8f64367240983e5ecea92096f -r d91185b2447f9baddd521690f4fb460c2fb70b3b doc/en/faq.txt --- a/doc/en/faq.txt +++ b/doc/en/faq.txt @@ -105,7 +105,7 @@ For simple applications and for people experienced with nose_ or unittest-style test setup using `xUnit style setup`_ probably -feels natural. For larger test suites, parameterized testing +feels natural. For larger test suites, parametrized testing or setup of complex test resources using funcargs_ may feel more natural. Moreover, funcargs are ideal for writing advanced test support code (like e.g. the monkeypatch_, the tmpdir_ or capture_ funcargs) https://bitbucket.org/hpk42/pytest/commits/5fc366c50b56/ Changeset: 5fc366c50b56 User: flub Date: 2015-02-12 09:32:32+00:00 Summary: Merged in jeffwidman/pytest/jeffwidman/fix-faq-grammar-and-spelling-1423641159173 (pull request #246) Fix FAQ grammar and spelling Affected #: 1 file diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c doc/en/faq.txt --- a/doc/en/faq.txt +++ b/doc/en/faq.txt @@ -30,15 +30,15 @@ If you are using trial's unittest.TestCase chances are that you can just run your tests even if you return Deferreds. In addition, there also is a dedicated `pytest-twisted -`_ plugin which allows to -return deferreds from pytest-style tests, allowing to use +`_ plugin which allows you to +return deferreds from pytest-style tests, allowing the use of :ref:`fixtures` and other features. how does pytest work with Django? ++++++++++++++++++++++++++++++++++++++++++++++ In 2012, some work is going into the `pytest-django plugin `_. It substitutes the usage of Django's -``manage.py test`` and allows to use all pytest features_ most of which +``manage.py test`` and allows the use of all pytest features_ most of which are not available from Django directly. .. _features: features.html @@ -49,7 +49,7 @@ Around 2007 (version ``0.8``) some people thought that ``pytest`` was using too much "magic". It had been part of the `pylib`_ which -contains a lot of unreleated python library code. Around 2010 there +contains a lot of unrelated python library code. Around 2010 there was a major cleanup refactoring, which removed unused or deprecated code and resulted in the new ``pytest`` PyPI package which strictly contains only test-related code. This release also brought a complete pluginification @@ -63,7 +63,7 @@ Nowadays, ``pytest`` explicitely rewrites assert statements in test modules in order to provide more useful :ref:`assert feedback `. This completely avoids previous issues of confusing assertion-reporting. -It also means, that you can use Python's ``-O`` optimization without loosing +It also means, that you can use Python's ``-O`` optimization without losing assertions in test modules. ``pytest`` contains a second, mostly obsolete, assert debugging technique, @@ -152,13 +152,13 @@ Issues with pytest, multiprocess and setuptools? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -On windows the multiprocess package will instantiate sub processes +On Windows the multiprocess package will instantiate sub processes by pickling and thus implicitly re-import a lot of local modules. Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'`` protect its generated command line script. This leads to infinite recursion when running a test that instantiates Processes. -As of middle 2013, there shouldn't be a problem anymore when you +As of mid-2013, there shouldn't be a problem anymore when you use the standard setuptools (note that distribute has been merged back into setuptools which is now shipped directly with virtualenv). Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Thu Feb 12 10:32:40 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 12 Feb 2015 09:32:40 -0000 Subject: [Pytest-commit] commit/pytest: flub: Merged in jeffwidman/pytest/jeffwidman/fix-faq-grammar-and-spelling-1423641159173 (pull request #246) Message-ID: <20150212093240.20766.44789@app12.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/5fc366c50b56/ Changeset: 5fc366c50b56 User: flub Date: 2015-02-12 09:32:32+00:00 Summary: Merged in jeffwidman/pytest/jeffwidman/fix-faq-grammar-and-spelling-1423641159173 (pull request #246) Fix FAQ grammar and spelling Affected #: 1 file diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c doc/en/faq.txt --- a/doc/en/faq.txt +++ b/doc/en/faq.txt @@ -30,15 +30,15 @@ If you are using trial's unittest.TestCase chances are that you can just run your tests even if you return Deferreds. In addition, there also is a dedicated `pytest-twisted -`_ plugin which allows to -return deferreds from pytest-style tests, allowing to use +`_ plugin which allows you to +return deferreds from pytest-style tests, allowing the use of :ref:`fixtures` and other features. how does pytest work with Django? ++++++++++++++++++++++++++++++++++++++++++++++ In 2012, some work is going into the `pytest-django plugin `_. It substitutes the usage of Django's -``manage.py test`` and allows to use all pytest features_ most of which +``manage.py test`` and allows the use of all pytest features_ most of which are not available from Django directly. .. _features: features.html @@ -49,7 +49,7 @@ Around 2007 (version ``0.8``) some people thought that ``pytest`` was using too much "magic". It had been part of the `pylib`_ which -contains a lot of unreleated python library code. Around 2010 there +contains a lot of unrelated python library code. Around 2010 there was a major cleanup refactoring, which removed unused or deprecated code and resulted in the new ``pytest`` PyPI package which strictly contains only test-related code. This release also brought a complete pluginification @@ -63,7 +63,7 @@ Nowadays, ``pytest`` explicitely rewrites assert statements in test modules in order to provide more useful :ref:`assert feedback `. This completely avoids previous issues of confusing assertion-reporting. -It also means, that you can use Python's ``-O`` optimization without loosing +It also means, that you can use Python's ``-O`` optimization without losing assertions in test modules. ``pytest`` contains a second, mostly obsolete, assert debugging technique, @@ -152,13 +152,13 @@ Issues with pytest, multiprocess and setuptools? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -On windows the multiprocess package will instantiate sub processes +On Windows the multiprocess package will instantiate sub processes by pickling and thus implicitly re-import a lot of local modules. Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'`` protect its generated command line script. This leads to infinite recursion when running a test that instantiates Processes. -As of middle 2013, there shouldn't be a problem anymore when you +As of mid-2013, there shouldn't be a problem anymore when you use the standard setuptools (note that distribute has been merged back into setuptools which is now shipped directly with virtualenv). Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From issues-reply at bitbucket.org Fri Feb 13 19:46:39 2015 From: issues-reply at bitbucket.org (Lucas Cimon) Date: Fri, 13 Feb 2015 18:46:39 -0000 Subject: [Pytest-commit] Issue #680: Cannot disable capturing with --dist=distmode (hpk42/pytest) Message-ID: <20150213184639.8771.18470@app11.ash-private.bitbucket.org> New issue 680: Cannot disable capturing with --dist=distmode https://bitbucket.org/hpk42/pytest/issue/680/cannot-disable-capturing-with-dist Lucas Cimon: To reproduce this issue, create a file named **stupid\_test.py** with the following code : ```python def test_unicode(): print "*[PRINT TO STDOUT]*" assert True ``` Then run the following: ``` $ py.test -v --capture=no --tx='1*popen' --dist=no stupid_test.py # -> standard output contains "*[PRINT TO STDOUT]*" $ py.test -v --capture=no --tx='1*popen' --dist=load stupid_test.py # -> standard output is captured $ py.test -v --capture=no --tx='1*popen' --dist=each stupid_test.py # -> standard output is captured ``` I'm using the following version: ``` platform linux2 -- Python 2.7.6 -- py-1.4.26 -- pytest-2.6.4 -- /usr/bin/python ``` From issues-reply at bitbucket.org Sat Feb 14 13:20:18 2015 From: issues-reply at bitbucket.org (Ronny Pfannschmidt) Date: Sat, 14 Feb 2015 12:20:18 -0000 Subject: [Pytest-commit] Issue #681: covariant parametrisation (hpk42/pytest) Message-ID: <20150214122018.13650.48884@app05.ash-private.bitbucket.org> New issue 681: covariant parametrisation https://bitbucket.org/hpk42/pytest/issue/681/covariant-parametrisation Ronny Pfannschmidt: i just found a use-case where i'd want to parametrize a test that takes a parametrized fixture and have a different parameter parametrized accordingly From issues-reply at bitbucket.org Sat Feb 14 16:59:51 2015 From: issues-reply at bitbucket.org (Unknown Name) Date: Sat, 14 Feb 2015 15:59:51 -0000 Subject: [Pytest-commit] Issue #682: Check if several functions are called (hpk42/pytest) Message-ID: <20150214155951.1377.13274@app08.ash-private.bitbucket.org> New issue 682: Check if several functions are called https://bitbucket.org/hpk42/pytest/issue/682/check-if-several-functions-are-called Unknown Name: I wanted to check if several functions were called during the test and I implemented the class bellow. I don't know if you're interested in it. Unfortunately, the code with the tests using this class turned out to be useless. So I don't even know if it is useful. ```python class StateTesting: """A class to test if some functions are called.""" def __init__(self, final_states): """ :param final_states: A list of final states. :type final_states: list """ self.len = len(final_states) self.final_states = final_states self.states = [False] * self.len @staticmethod def test(final_states): """Create a decorator to test the function. :param final_states: A list of final states. :type final_states: list :return: A decorator. :rtype: func """ def decorator(func): def wrapper(*args, **kwargs): obj = StateTesting(final_states) func(obj, *args, **kwargs) # Test if the functions have been called for i in range(obj.len): assert obj.states[i] == obj.final_states[i] return wrapper return decorator def decorate(self, callback, index): """Return a function setting `self.states[index]` to `True` and calling `callback`. :param callback: A callback to be called. :param index: The index to be toggled. :type callback: callable :type index: int :rtype: func """ def func(*args, **kwargs): self.states[index] = True callback(*args, **kwargs) return func ``` To be used like that: ```python def callback1(data): pass def callback2(data): pass def callback3(data): pass @StateTesting.test([True, False, True]) def test_sth(state_obj): process(arg1, arg2, callback=state_obj.decorate(callback1, 0)) process_not_to_be_supposed_to_call_its_callback(arg3, callback=state_obj.decorate(callback2, 1)) other_process(arg, callback=state_obj.decorate(callback1, 2)) ``` Thanks. From issues-reply at bitbucket.org Sat Feb 14 19:28:53 2015 From: issues-reply at bitbucket.org (astrofrog) Date: Sat, 14 Feb 2015 18:28:53 -0000 Subject: [Pytest-commit] Issue #683: Bug with parameterized classes when running tests twice (hpk42/pytest) Message-ID: <20150214182853.15707.91195@app03.ash-private.bitbucket.org> New issue 683: Bug with parameterized classes when running tests twice https://bitbucket.org/hpk42/pytest/issue/683/bug-with-parameterized-classes-when astrofrog: If we consider the following example and place it in a file called ``test_double.py``: ``` import pytest class TestA(object): pass @pytest.mark.parametrize(('model_class'), [1,2,3]) class TestB(TestA): def test_1(self, model_class): pass ``` We can then try and run this with: ``` py.test test_double.py test_double.py ``` This produces the following error: ``` ========================================================= test session starts ========================================================== platform darwin -- Python 3.4.2 -- py-1.4.23 -- pytest-2.6.1 plugins: cov, xdist collected 3 items / 1 errors test_double.py ... ================================================================ ERRORS ================================================================ ___________________________________________________ ERROR collecting test_double.py ____________________________________________________ ../Library/Python/3.4/lib/python/site-packages/_pytest/runner.py:139: in __init__ self.result = func() ../Library/Python/3.4/lib/python/site-packages/_pytest/main.py:438: in _memocollect return self._memoizedcall('_collected', lambda: list(self.collect())) ../Library/Python/3.4/lib/python/site-packages/_pytest/main.py:315: in _memoizedcall res = function() ../Library/Python/3.4/lib/python/site-packages/_pytest/main.py:438: in return self._memoizedcall('_collected', lambda: list(self.collect())) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:538: in collect return super(Instance, self).collect() ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:333: in collect res = self.makeitem(name, obj) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:345: in makeitem collector=self, name=name, obj=obj) ../Library/Python/3.4/lib/python/site-packages/_pytest/main.py:166: in call_matching_hooks return hookmethod.pcall(plugins, **kwargs) ../Library/Python/3.4/lib/python/site-packages/_pytest/core.py:417: in pcall return self._docall(methods, kwargs) ../Library/Python/3.4/lib/python/site-packages/_pytest/core.py:424: in _docall res = mc.execute() ../Library/Python/3.4/lib/python/site-packages/_pytest/core.py:315: in execute res = method(**kwargs) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:236: in pytest_pycollect_makeitem return list(collector._genfunctions(name, obj)) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:361: in _genfunctions gentesthook.pcall(plugins, metafunc=metafunc) ../Library/Python/3.4/lib/python/site-packages/_pytest/core.py:417: in pcall return self._docall(methods, kwargs) ../Library/Python/3.4/lib/python/site-packages/_pytest/core.py:424: in _docall res = mc.execute() ../Library/Python/3.4/lib/python/site-packages/_pytest/core.py:315: in execute res = method(**kwargs) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:146: in pytest_generate_tests metafunc.parametrize(*marker.args, **marker.kwargs) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:836: in parametrize param_index) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:717: in setmulti self._checkargnotcontained(arg) ../Library/Python/3.4/lib/python/site-packages/_pytest/python.py:700: in _checkargnotcontained raise ValueError("duplicate %r" %(arg,)) E ValueError: duplicate 'model_class' ``` We discovered this because when running Astropy tests twice in a row: ``` import astropy astropy.test() astropy.test() ``` the same error occurs. From issues-reply at bitbucket.org Sun Feb 15 09:56:41 2015 From: issues-reply at bitbucket.org (glyph) Date: Sun, 15 Feb 2015 08:56:41 -0000 Subject: [Pytest-commit] Issue #215: retry installation steps (hpk42/tox) Message-ID: <20150215085641.16252.14705@app05.ash-private.bitbucket.org> New issue 215: retry installation steps https://bitbucket.org/hpk42/tox/issue/215/retry-installation-steps glyph: On various test infrastructures (Travis-CI in particular) PyPI is frequently unavailable. When this is so, I would like tox to re-try the `pip install` step but not the actual testing step. If actual tests fail, I would like to see a failure. If installation fails, I would like to just re-attempt installation? for intermittent failures, I'd like to do this basically forever, for "hard" failures where packages appear to have been removed from the index, for example, reporting a failure might be fine. There doesn't seem to be a way to do this, and I can't work around it because there also doesn't seem to be a way to tell tox to *just* create its virtual environments. Perhaps I just haven't found the relevant documentation yet though. From commits-noreply at bitbucket.org Mon Feb 16 09:51:20 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 16 Feb 2015 08:51:20 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150216085120.15538.84115@app10.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/82fe926a4f8a/ Changeset: 82fe926a4f8a Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-16 08:40:48+00:00 Summary: simply copy the files, fails all tests Affected #: 8 files diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 _pytest/cache.py --- /dev/null +++ b/_pytest/cache.py @@ -0,0 +1,201 @@ +import py +import pytest +import json + + +class Cache: + def __init__(self, config): + self.config = config + self._cachedir = getrootdir(config, ".cache") + self.trace = config.trace.root.get("cache") + if config.getvalue("clearcache"): + self.trace("clearing cachedir") + if self._cachedir.check(): + self._cachedir.remove() + self._cachedir.mkdir() + + def makedir(self, name): + """ return a directory path object with the given name. If the + directory does not yet exist, it will be created. You can use it + to manage files likes e. g. store/retrieve database + dumps across test sessions. + + :param name: must be a string not containing a ``/`` separator. + Make sure the name contains your plugin or application + identifiers to prevent clashes with other cache users. + """ + if name.count("/") != 0: + raise ValueError("name is not allowed to contain '/'") + p = self._cachedir.join("d/" + name) + p.ensure(dir=1) + return p + + def _getpath(self, key): + if not key.count("/") > 1: + raise KeyError("Key must be of format 'dir/.../subname") + return self._cachedir.join(key) + + def _getvaluepath(self, key): + p = self._getpath("v/" + key) + p.dirpath().ensure(dir=1) + return p + + def get(self, key, default): + """ return cached value for the given key. If no value + was yet cached or the value cannot be read, the specified + default is returned. + + :param key: must be a ``/`` separated value. Usually the first + name is the name of your plugin or your application. + :param default: must be provided in case of a cache-miss or + invalid cache values. + + """ + path = self._getvaluepath(key) + if path.check(): + try: + with path.open("r") as f: + return json.load(f) + except ValueError: + self.trace("cache-invalid at %s" % (path,)) + return default + + def set(self, key, value): + """ save value for the given key. + + :param key: must be a ``/`` separated value. Usually the first + name is the name of your plugin or your application. + :param value: must be of any combination of basic + python types, including nested types + like e. g. lists of dictionaries. + """ + path = self._getvaluepath(key) + with path.open("w") as f: + self.trace("cache-write %s: %r" % (key, value,)) + json.dump(value, f, indent=2, sort_keys=True) + + +### XXX consider shifting part of the below to pytest config object + +def getrootdir(config, name): + """ return a best-effort root subdir for this test run. + + Starting from files specified at the command line (or cwd) + search starts upward for the first "tox.ini", "pytest.ini", + "setup.cfg" or "setup.py" file. The first directory containing + such a file will be used to return a named subdirectory + (py.path.local object). + + """ + if config.inicfg: + p = py.path.local(config.inicfg.config.path).dirpath() + else: + inibasenames = ["setup.py", "setup.cfg", "tox.ini", "pytest.ini"] + for x in getroot(config.args, inibasenames): + p = x.dirpath() + break + else: + p = py.path.local() + config.trace.get("warn")("no rootdir found, using %s" % p) + subdir = p.join(name) + config.trace("root %s: %s" % (name, subdir)) + return subdir + +def getroot(args, inibasenames): + args = [x for x in args if not str(x).startswith("-")] + if not args: + args = [py.path.local()] + for arg in args: + arg = py.path.local(arg) + for base in arg.parts(reverse=True): + for inibasename in inibasenames: + p = base.join(inibasename) + if p.check(): + yield p + + +import py +import pytest + + +def pytest_addoption(parser): + group = parser.getgroup("general") + group.addoption( + '--lf', action='store_true', dest="lf", + help="rerun only the tests that failed at the last run (or all if none failed)") + group.addoption( + '--ff', action='store_true', dest="failedfirst", + help="run all tests but run the last failures first. This may re-order " + "tests and thus lead to repeated fixture setup/teardown") + group.addoption( + '--cache', action='store_true', dest="showcache", + help="show cache contents, don't perform collection or tests") + group.addoption( + '--clearcache', action='store_true', dest="clearcache", + help="remove all cache contents at start of test run.") + group.addoption( + '--looponchange', action='store_true', dest='looponchange', + help='rerun every time the workdir changes') + group.addoption( + '--looponfail', action='store_true', dest='looponfail', + help='rerun every time the workdir changes') + parser.addini( + "looponchangeroots", type="pathlist", + help="directories to check for changes", default=[py.path.local()]) + + +def pytest_cmdline_main(config): + if config.option.showcache: + from _pytest.main import wrap_session + return wrap_session(config, showcache) + if config.option.looponchange or config.option.looponfail: + from .onchange import looponchange + return looponchange(config) + + + at pytest.mark.tryfirst +def pytest_configure(config): + from .cache import Cache + from .lastfail import LFPlugin + config.cache = cache = Cache(config) + config.pluginmanager.register(LFPlugin(config), "lfplugin") + +def pytest_report_header(config): + if config.option.verbose: + relpath = py.path.local().bestrelpath(config.cache._cachedir) + return "cachedir: %s" % config.cache._cachedir + +def showcache(config, session): + from pprint import pprint + tw = py.io.TerminalWriter() + tw.line("cachedir: " + str(config.cache._cachedir)) + if not config.cache._cachedir.check(): + tw.line("cache is empty") + return 0 + dummy = object() + basedir = config.cache._cachedir + vdir = basedir.join("v") + tw.sep("-", "cache values") + for valpath in vdir.visit(lambda x: x.check(file=1)): + key = valpath.relto(vdir).replace(valpath.sep, "/") + val = config.cache.get(key, dummy) + if val is dummy: + tw.line("%s contains unreadable content, " + "will be ignored" % key) + else: + tw.line("%s contains:" % key) + stream = py.io.TextIO() + pprint(val, stream=stream) + for line in stream.getvalue().splitlines(): + tw.line(" " + line) + + ddir = basedir.join("d") + if ddir.check(dir=1) and ddir.listdir(): + tw.sep("-", "cache directories") + for p in basedir.join("d").visit(): + #if p.check(dir=1): + # print("%s/" % p.relto(basedir)) + if p.check(file=1): + key = p.relto(basedir) + tw.line("%s is a file of length %d" % ( + key, p.size())) diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 _pytest/lastfail.py --- /dev/null +++ b/_pytest/lastfail.py @@ -0,0 +1,65 @@ + + +class LFPlugin: + """ Plugin which implements the --lf (run last-failing) option """ + def __init__(self, config): + self.config = config + active_keys = 'lf', 'failedfirst', 'looponfail' + self.active = any(config.getvalue(key) for key in active_keys) + if self.active: + self.lastfailed = config.cache.get("cache/lastfailed", {}) + else: + self.lastfailed = {} + + def pytest_report_header(self): + if self.active: + if not self.lastfailed: + mode = "run all (no recorded failures)" + else: + mode = "rerun last %d failures%s" % ( + len(self.lastfailed), + " first" if self.config.getvalue("failedfirst") else "") + return "run-last-failure: %s" % mode + + def pytest_runtest_logreport(self, report): + if report.failed and "xfail" not in report.keywords: + self.lastfailed[report.nodeid] = True + elif not report.failed: + if report.when == "call": + self.lastfailed.pop(report.nodeid, None) + + def pytest_collectreport(self, report): + passed = report.outcome in ('passed', 'skipped') + if passed: + if report.nodeid in self.lastfailed: + self.lastfailed.pop(report.nodeid) + self.lastfailed.update( + (item.nodeid, True) + for item in report.result) + else: + self.lastfailed[report.nodeid] = True + + def pytest_collection_modifyitems(self, session, config, items): + if self.active and self.lastfailed: + previously_failed = [] + previously_passed = [] + for item in items: + if item.nodeid in self.lastfailed: + previously_failed.append(item) + else: + previously_passed.append(item) + if not previously_failed and previously_passed: + # running a subset of all tests with recorded failures outside + # of the set of tests currently executing + pass + elif self.config.getvalue("failedfirst"): + items[:] = previously_failed + previously_passed + else: + items[:] = previously_failed + config.hook.pytest_deselected(items=previously_passed) + + def pytest_sessionfinish(self, session): + config = self.config + if config.getvalue("showcache") or hasattr(config, "slaveinput"): + return + config.cache.set("cache/lastfailed", self.lastfailed) diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 _pytest/onchange.py --- /dev/null +++ b/_pytest/onchange.py @@ -0,0 +1,75 @@ +import py + + +SCRIPT = """ +import pytest +pytest.main(%r) +""" + + +def looponchange(config): + newargs = config._origargs[:] + newargs.remove('--looponchange') + stats = StatRecorder(config.getini('looponchangeroots')) + command = py.std.functools.partial( + py.std.subprocess.call, [ + py.std.sys.executable, + '-c', SCRIPT % newargs]) + loop_forever(stats, command) + return 2 + + +def loop_forever(stats, command): + while True: + stats.waitonchange() + command() + + +class StatRecorder(object): + def __init__(self, rootdirlist): + self.rootdirlist = rootdirlist + self.statcache = {} + self.check() # snapshot state + + def fil(self, p): + return p.check(file=1, dotfile=0) and p.ext != ".pyc" + def rec(self, p): + return p.check(dotfile=0) + + def waitonchange(self, checkinterval=1.0): + while 1: + changed = self.check() + if changed: + return + py.std.time.sleep(checkinterval) + + def check(self, removepycfiles=True): + changed = False + statcache = self.statcache + newstat = {} + for rootdir in self.rootdirlist: + for path in rootdir.visit(self.fil, self.rec): + oldstat = statcache.pop(path, None) + try: + newstat[path] = curstat = path.stat() + except py.error.ENOENT: + if oldstat: + changed = True + else: + if oldstat: + if oldstat.mtime != curstat.mtime or \ + oldstat.size != curstat.size: + changed = True + py.builtin.print_("# MODIFIED", path) + if removepycfiles and path.ext == ".py": + pycfile = path + "c" + if pycfile.check(): + pycfile.remove() + + else: + changed = True + if statcache: + changed = True + self.statcache = newstat + return changed + diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 _pytest/plugin.py --- /dev/null +++ b/_pytest/plugin.py @@ -0,0 +1,85 @@ +import py +import pytest + + +def pytest_addoption(parser): + group = parser.getgroup("general") + group.addoption( + '--lf', action='store_true', dest="lf", + help="rerun only the tests that failed at the last run (or all if none failed)") + group.addoption( + '--ff', action='store_true', dest="failedfirst", + help="run all tests but run the last failures first. This may re-order " + "tests and thus lead to repeated fixture setup/teardown") + group.addoption( + '--cache', action='store_true', dest="showcache", + help="show cache contents, don't perform collection or tests") + group.addoption( + '--clearcache', action='store_true', dest="clearcache", + help="remove all cache contents at start of test run.") + group.addoption( + '--looponchange', action='store_true', dest='looponchange', + help='rerun every time the workdir changes') + group.addoption( + '--looponfail', action='store_true', dest='looponfail', + help='rerun every time the workdir changes') + parser.addini( + "looponchangeroots", type="pathlist", + help="directories to check for changes", default=[py.path.local()]) + + +def pytest_cmdline_main(config): + if config.option.showcache: + from _pytest.main import wrap_session + return wrap_session(config, showcache) + if config.option.looponchange or config.option.looponfail: + from .onchange import looponchange + return looponchange(config) + + + at pytest.mark.tryfirst +def pytest_configure(config): + from .cache import Cache + from .lastfail import LFPlugin + config.cache = cache = Cache(config) + config.pluginmanager.register(LFPlugin(config), "lfplugin") + +def pytest_report_header(config): + if config.option.verbose: + relpath = py.path.local().bestrelpath(config.cache._cachedir) + return "cachedir: %s" % config.cache._cachedir + +def showcache(config, session): + from pprint import pprint + tw = py.io.TerminalWriter() + tw.line("cachedir: " + str(config.cache._cachedir)) + if not config.cache._cachedir.check(): + tw.line("cache is empty") + return 0 + dummy = object() + basedir = config.cache._cachedir + vdir = basedir.join("v") + tw.sep("-", "cache values") + for valpath in vdir.visit(lambda x: x.check(file=1)): + key = valpath.relto(vdir).replace(valpath.sep, "/") + val = config.cache.get(key, dummy) + if val is dummy: + tw.line("%s contains unreadable content, " + "will be ignored" % key) + else: + tw.line("%s contains:" % key) + stream = py.io.TextIO() + pprint(val, stream=stream) + for line in stream.getvalue().splitlines(): + tw.line(" " + line) + + ddir = basedir.join("d") + if ddir.check(dir=1) and ddir.listdir(): + tw.sep("-", "cache directories") + for p in basedir.join("d").visit(): + #if p.check(dir=1): + # print("%s/" % p.relto(basedir)) + if p.check(file=1): + key = p.relto(basedir) + tw.line("%s is a file of length %d" % ( + key, p.size())) diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 testing/test_cache.py --- /dev/null +++ b/testing/test_cache.py @@ -0,0 +1,54 @@ +import os +import pytest +import shutil +import py + +pytest_plugins = "pytester", + +class TestNewAPI: + def test_config_cache_makedir(self, testdir): + testdir.makeini("[pytest]") + config = testdir.parseconfigure() + pytest.raises(ValueError, lambda: + config.cache.makedir("key/name")) + p = config.cache.makedir("name") + assert p.check() + + def test_config_cache_dataerror(self, testdir): + testdir.makeini("[pytest]") + config = testdir.parseconfigure() + cache = config.cache + pytest.raises(TypeError, lambda: cache.set("key/name", cache)) + config.cache.set("key/name", 0) + config.cache._getvaluepath("key/name").write("123invalid") + val = config.cache.get("key/name", -2) + assert val == -2 + + def test_config_cache(self, testdir): + testdir.makeconftest(""" + def pytest_configure(config): + # see that we get cache information early on + assert hasattr(config, "cache") + """) + testdir.makepyfile(""" + def test_session(pytestconfig): + assert hasattr(pytestconfig, "cache") + """) + result = testdir.runpytest() + assert result.ret == 0 + result.stdout.fnmatch_lines(["*1 passed*"]) + + def XXX_test_cachefuncarg(self, testdir): + testdir.makepyfile(""" + import pytest + def test_cachefuncarg(cache): + val = cache.get("some/thing", None) + assert val is None + cache.set("some/thing", [1]) + pytest.raises(TypeError, lambda: cache.get("some/thing")) + val = cache.get("some/thing", []) + assert val == [1] + """) + result = testdir.runpytest() + assert result.ret == 0 + result.stdout.fnmatch_lines(["*1 passed*"]) diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 testing/test_lastfailed.py --- /dev/null +++ b/testing/test_lastfailed.py @@ -0,0 +1,235 @@ +import os +import pytest +import shutil +import py + +pytest_plugins = "pytester", + + +class TestLastFailed: + @pytest.mark.skipif("sys.version_info < (2,6)") + def test_lastfailed_usecase(self, testdir, monkeypatch): + monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) + p = testdir.makepyfile(""" + def test_1(): + assert 0 + def test_2(): + assert 0 + def test_3(): + assert 1 + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + p.write(py.code.Source(""" + def test_1(): + assert 1 + + def test_2(): + assert 1 + + def test_3(): + assert 0 + """)) + result = testdir.runpytest("--lf") + result.stdout.fnmatch_lines([ + "*2 passed*1 desel*", + ]) + result = testdir.runpytest("--lf") + result.stdout.fnmatch_lines([ + "*1 failed*2 passed*", + ]) + result = testdir.runpytest("--lf", "--clearcache") + result.stdout.fnmatch_lines([ + "*1 failed*2 passed*", + ]) + + # Run this again to make sure clearcache is robust + if os.path.isdir('.cache'): + shutil.rmtree('.cache') + result = testdir.runpytest("--lf", "--clearcache") + result.stdout.fnmatch_lines([ + "*1 failed*2 passed*", + ]) + + def test_failedfirst_order(self, testdir): + always_pass = testdir.tmpdir.join('test_a.py').write(py.code.Source(""" + def test_always_passes(): + assert 1 + """)) + always_fail = testdir.tmpdir.join('test_b.py').write(py.code.Source(""" + def test_always_fails(): + assert 0 + """)) + result = testdir.runpytest() + # Test order will be collection order; alphabetical + result.stdout.fnmatch_lines([ + "test_a.py*", + "test_b.py*", + ]) + result = testdir.runpytest("--lf", "--ff") + # Test order will be failing tests firs + result.stdout.fnmatch_lines([ + "test_b.py*", + "test_a.py*", + ]) + + @pytest.mark.skipif("sys.version_info < (2,6)") + def test_lastfailed_difference_invocations(self, testdir, monkeypatch): + monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) + testdir.makepyfile(test_a=""" + def test_a1(): + assert 0 + def test_a2(): + assert 1 + """, test_b=""" + def test_b1(): + assert 0 + """) + p = testdir.tmpdir.join("test_a.py") + p2 = testdir.tmpdir.join("test_b.py") + + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + result = testdir.runpytest("--lf", p2) + result.stdout.fnmatch_lines([ + "*1 failed*", + ]) + p2.write(py.code.Source(""" + def test_b1(): + assert 1 + """)) + result = testdir.runpytest("--lf", p2) + result.stdout.fnmatch_lines([ + "*1 passed*", + ]) + result = testdir.runpytest("--lf", p) + result.stdout.fnmatch_lines([ + "*1 failed*1 desel*", + ]) + + @pytest.mark.skipif("sys.version_info < (2,6)") + def test_lastfailed_usecase_splice(self, testdir, monkeypatch): + monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) + p1 = testdir.makepyfile(""" + def test_1(): + assert 0 + """) + p2 = testdir.tmpdir.join("test_something.py") + p2.write(py.code.Source(""" + def test_2(): + assert 0 + """)) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + result = testdir.runpytest("--lf", p2) + result.stdout.fnmatch_lines([ + "*1 failed*", + ]) + result = testdir.runpytest("--lf") + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + + def test_lastfailed_xpass(self, testdir): + rep = testdir.inline_runsource1(""" + import pytest + @pytest.mark.xfail + def test_hello(): + assert 1 + """) + config = testdir.parseconfigure() + lastfailed = config.cache.get("cache/lastfailed", -1) + assert not lastfailed + + def test_lastfailed_collectfailure(self, testdir, monkeypatch): + + testdir.makepyfile(test_maybe=""" + import py + env = py.std.os.environ + if '1' == env['FAILIMPORT']: + raise ImportError('fail') + def test_hello(): + assert '0' == env['FAILTEST'] + """) + + def rlf(fail_import, fail_run): + monkeypatch.setenv('FAILIMPORT', fail_import) + monkeypatch.setenv('FAILTEST', fail_run) + + testdir.runpytest('-q') + config = testdir.parseconfigure() + lastfailed = config.cache.get("cache/lastfailed", -1) + return lastfailed + + lastfailed = rlf(fail_import=0, fail_run=0) + assert not lastfailed + + lastfailed = rlf(fail_import=1, fail_run=0) + assert list(lastfailed) == ['test_maybe.py'] + + 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=""" + import py + env = py.std.os.environ + if '1' == env['FAILIMPORT']: + raise ImportError('fail') + def test_hello(): + assert '0' == env['FAILTEST'] + """) + + testdir.makepyfile(test_maybe2=""" + import py + env = py.std.os.environ + if '1' == env['FAILIMPORT']: + raise ImportError('fail') + def test_hello(): + assert '0' == env['FAILTEST'] + + def test_pass(): + pass + """) + + def rlf(fail_import, fail_run, args=()): + monkeypatch.setenv('FAILIMPORT', fail_import) + monkeypatch.setenv('FAILTEST', fail_run) + + result = testdir.runpytest('-q', '--lf', *args) + config = testdir.parseconfigure() + lastfailed = config.cache.get("cache/lastfailed", -1) + return result, lastfailed + + result, lastfailed = rlf(fail_import=0, fail_run=0) + assert not lastfailed + result.stdout.fnmatch_lines([ + '*3 passed*', + ]) + + 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 + result, lastfailed = rlf(fail_import=0, fail_run=0, + args=('test_maybe2.py',)) + assert list(lastfailed) == ['test_maybe.py'] + result.stdout.fnmatch_lines([ + '*2 passed*', + ]) diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 testing/test_onchange.py --- /dev/null +++ b/testing/test_onchange.py @@ -0,0 +1,88 @@ +from pytest_cache.onchange import StatRecorder + +class TestStatRecorder: + def test_filechange(self, tmpdir): + tmp = tmpdir + hello = tmp.ensure("hello.py") + sd = StatRecorder([tmp]) + changed = sd.check() + assert not changed + + hello.write("world") + changed = sd.check() + assert changed + + (hello + "c").write("hello") + changed = sd.check() + assert not changed + + p = tmp.ensure("new.py") + changed = sd.check() + assert changed + + p.remove() + changed = sd.check() + assert changed + + tmp.join("a", "b", "c.py").ensure() + changed = sd.check() + assert changed + + tmp.join("a", "c.txt").ensure() + changed = sd.check() + assert changed + changed = sd.check() + assert not changed + + tmp.join("a").remove() + changed = sd.check() + assert changed + + def test_dirchange(self, tmpdir): + tmp = tmpdir + hello = tmp.ensure("dir", "hello.py") + sd = StatRecorder([tmp]) + assert not sd.fil(tmp.join("dir")) + + def test_filechange_deletion_race(self, tmpdir, monkeypatch): + tmp = tmpdir + sd = StatRecorder([tmp]) + changed = sd.check() + assert not changed + + p = tmp.ensure("new.py") + changed = sd.check() + assert changed + + p.remove() + # make check()'s visit() call return our just removed + # path as if we were in a race condition + monkeypatch.setattr(tmp, 'visit', lambda *args: [p]) + + changed = sd.check() + assert changed + + def test_pycremoval(self, tmpdir): + tmp = tmpdir + hello = tmp.ensure("hello.py") + sd = StatRecorder([tmp]) + changed = sd.check() + assert not changed + + pycfile = hello + "c" + pycfile.ensure() + hello.write("world") + changed = sd.check() + assert changed + assert not pycfile.check() + + def test_waitonchange(self, tmpdir, monkeypatch): + tmp = tmpdir + sd = StatRecorder([tmp]) + + l = [True, False] + monkeypatch.setattr(StatRecorder, 'check', lambda self: l.pop()) + sd.waitonchange(checkinterval=0.2) + assert not l + + diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 testing/test_plugin.py --- /dev/null +++ b/testing/test_plugin.py @@ -0,0 +1,50 @@ +import os +import pytest +import shutil +import py + +pytest_plugins = "pytester", + +def test_version(): + import pytest_cache + assert pytest_cache.__version__ + +def test_cache_reportheader(testdir): + p = testdir.makepyfile(""" + def test_hello(): + pass + """) + cachedir = p.dirpath(".cache") + result = testdir.runpytest("-v") + result.stdout.fnmatch_lines([ + "cachedir: %s" % cachedir, + ]) + +def test_cache_show(testdir): + result = testdir.runpytest("--cache") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + "*cache is empty*" + ]) + p = testdir.makeconftest(""" + def pytest_configure(config): + config.cache.set("my/name", [1,2,3]) + config.cache.set("other/some", {1:2}) + dp = config.cache.makedir("mydb") + dp.ensure("hello") + dp.ensure("world") + """) + result = testdir.runpytest() + assert result.ret == 0 + result = testdir.runpytest("--cache") + result.stdout.fnmatch_lines_random([ + "*cachedir:*", + "-*cache values*-", + "*my/name contains:", + " [1, 2, 3]", + "*other/some contains*", + " {*1*: 2}", + "-*cache directories*-", + "*mydb/hello*length 0*", + "*mydb/world*length 0*", + ]) https://bitbucket.org/hpk42/pytest/commits/19dff8006bd6/ Changeset: 19dff8006bd6 Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-16 08:50:34+00:00 Summary: make the tests pass, this is the baselevel for creating backward compat Affected #: 3 files diff -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 -r 19dff8006bd65f02f199c1e3ecec2a0a94a820b3 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -51,7 +51,7 @@ default_plugins = ( "mark main terminal runner python pdb unittest capture skipping " "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript " - "junitxml resultlog doctest").split() + "junitxml resultlog doctest cache").split() def _preloadplugins(): assert not _preinit diff -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 -r 19dff8006bd65f02f199c1e3ecec2a0a94a820b3 testing/test_onchange.py --- a/testing/test_onchange.py +++ b/testing/test_onchange.py @@ -1,4 +1,4 @@ -from pytest_cache.onchange import StatRecorder +from _pytest.onchange import StatRecorder class TestStatRecorder: def test_filechange(self, tmpdir): diff -r 82fe926a4f8ad6ef787b5411c1b0b69eb5191a57 -r 19dff8006bd65f02f199c1e3ecec2a0a94a820b3 testing/test_plugin.py --- a/testing/test_plugin.py +++ b/testing/test_plugin.py @@ -5,9 +5,6 @@ pytest_plugins = "pytester", -def test_version(): - import pytest_cache - assert pytest_cache.__version__ def test_cache_reportheader(testdir): p = testdir.makepyfile(""" Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 16 10:00:07 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 16 Feb 2015 09:00:07 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: delete unused file Message-ID: <20150216090007.19684.35498@app04.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/bc2cf073d49b/ Changeset: bc2cf073d49b Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-16 08:59:45+00:00 Summary: delete unused file Affected #: 1 file diff -r 19dff8006bd65f02f199c1e3ecec2a0a94a820b3 -r bc2cf073d49b5eaa8a403c2e1409e98f450d2ea5 _pytest/plugin.py --- a/_pytest/plugin.py +++ /dev/null @@ -1,85 +0,0 @@ -import py -import pytest - - -def pytest_addoption(parser): - group = parser.getgroup("general") - group.addoption( - '--lf', action='store_true', dest="lf", - help="rerun only the tests that failed at the last run (or all if none failed)") - group.addoption( - '--ff', action='store_true', dest="failedfirst", - help="run all tests but run the last failures first. This may re-order " - "tests and thus lead to repeated fixture setup/teardown") - group.addoption( - '--cache', action='store_true', dest="showcache", - help="show cache contents, don't perform collection or tests") - group.addoption( - '--clearcache', action='store_true', dest="clearcache", - help="remove all cache contents at start of test run.") - group.addoption( - '--looponchange', action='store_true', dest='looponchange', - help='rerun every time the workdir changes') - group.addoption( - '--looponfail', action='store_true', dest='looponfail', - help='rerun every time the workdir changes') - parser.addini( - "looponchangeroots", type="pathlist", - help="directories to check for changes", default=[py.path.local()]) - - -def pytest_cmdline_main(config): - if config.option.showcache: - from _pytest.main import wrap_session - return wrap_session(config, showcache) - if config.option.looponchange or config.option.looponfail: - from .onchange import looponchange - return looponchange(config) - - - at pytest.mark.tryfirst -def pytest_configure(config): - from .cache import Cache - from .lastfail import LFPlugin - config.cache = cache = Cache(config) - config.pluginmanager.register(LFPlugin(config), "lfplugin") - -def pytest_report_header(config): - if config.option.verbose: - relpath = py.path.local().bestrelpath(config.cache._cachedir) - return "cachedir: %s" % config.cache._cachedir - -def showcache(config, session): - from pprint import pprint - tw = py.io.TerminalWriter() - tw.line("cachedir: " + str(config.cache._cachedir)) - if not config.cache._cachedir.check(): - tw.line("cache is empty") - return 0 - dummy = object() - basedir = config.cache._cachedir - vdir = basedir.join("v") - tw.sep("-", "cache values") - for valpath in vdir.visit(lambda x: x.check(file=1)): - key = valpath.relto(vdir).replace(valpath.sep, "/") - val = config.cache.get(key, dummy) - if val is dummy: - tw.line("%s contains unreadable content, " - "will be ignored" % key) - else: - tw.line("%s contains:" % key) - stream = py.io.TextIO() - pprint(val, stream=stream) - for line in stream.getvalue().splitlines(): - tw.line(" " + line) - - ddir = basedir.join("d") - if ddir.check(dir=1) and ddir.listdir(): - tw.sep("-", "cache directories") - for p in basedir.join("d").visit(): - #if p.check(dir=1): - # print("%s/" % p.relto(basedir)) - if p.check(file=1): - key = p.relto(basedir) - tw.line("%s is a file of length %d" % ( - key, p.size())) Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Mon Feb 16 10:03:58 2015 From: builds at drone.io (Drone.io Build) Date: Mon, 16 Feb 2015 09:03:58 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 370 Message-ID: <20150216090345.126600.94638@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/370 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3849:19dff8006bd6 Author : Ronny Pfannschmidt Branch : copy-in-cache Message: make the tests pass, this is the baselevel for creating backward compat -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Mon Feb 16 10:16:42 2015 From: builds at drone.io (Drone.io Build) Date: Mon, 16 Feb 2015 09:16:42 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 371 Message-ID: <20150216091617.72257.21726@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/371 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3850:bc2cf073d49b Author : Ronny Pfannschmidt Branch : copy-in-cache Message: delete unused file -------------- next part -------------- An HTML attachment was scrubbed... URL: From issues-reply at bitbucket.org Tue Feb 17 18:56:23 2015 From: issues-reply at bitbucket.org (Nicolas Delaby) Date: Tue, 17 Feb 2015 17:56:23 -0000 Subject: [Pytest-commit] Issue #216: Adding new option install_deps_command or install_option (hpk42/tox) Message-ID: <20150217175623.30329.41764@app12.ash-private.bitbucket.org> New issue 216: Adding new option install_deps_command or install_option https://bitbucket.org/hpk42/tox/issue/216/adding-new-option-install_deps_command-or Nicolas Delaby: Hi, ## here is my problem: I'm trying to install a library I want to test with a custom argument to pip. To achieve this I'm using in my configuration file ```ini install_command = pip install {opts} {packages} --install-option="--foo=bar" ``` It works great, but because this install command is also used to install the testing dependencies. They start to fail because `--foo` is not recognized. ``` Running setup.py install for py usage: -c [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...] or: -c --help [cmd1 cmd2 ...] or: -c --help-commands or: -c cmd --help error: option --foo not recognized ``` ## Suggested solution 1: introduce a new option `install_deps_command`, that by default is using `install_command` value, to specify which command should be used to install the dependencies only. ## Suggested solution 2: introduce a new option `install_option` to append `--install-option="--foo=bar"` to the `pip install {opts} {packages}` command string. that is used to install the project we test only (excluding dependencies). example: ```ini install_option = --foo=bar ``` I'm willing to make the patch to solve this issue. From issues-reply at bitbucket.org Wed Feb 18 15:45:55 2015 From: issues-reply at bitbucket.org (aokhotin) Date: Wed, 18 Feb 2015 14:45:55 -0000 Subject: [Pytest-commit] Issue #684: parametrized fixture with session scope initialized twise (hpk42/pytest) Message-ID: <20150218144555.2209.89295@app12.ash-private.bitbucket.org> New issue 684: parametrized fixture with session scope initialized twise https://bitbucket.org/hpk42/pytest/issue/684/parametrized-fixture-with-session-scope aokhotin: I attached two files were bug reproduced. steps: ``` #!bash $ py.test --version This is pytest version 2.6.4, imported from /home/username/venv/local/lib/python2.7/site-packages/pytest.pyc ``` so there no any plugins. ``` #!bash py.test -sv ============================= test session starts ============================== platform linux2 -- Python 2.7.6 -- py-1.4.26 -- pytest-2.6.4 -- /home/username/venv/bin/python collected 21 items test_solar.py::test_one PASSED test_solar.py::test_three[pluto-1] sun '1' "sun '1'" - "pluto" PASSED test_solar.py::test_four[pluto-1] PASSED test_solar.py::test_three[pluto-2] sun '2' "sun '2'" - "pluto" PASSED test_solar.py::test_four[pluto-2] PASSED test_solar.py::test_three[neptun-2] "sun '2'" - "neptun" PASSED test_solar.py::test_four[neptun-2] PASSED test_solar.py::test_three[neptun-1] sun '1' "sun '1'" - "neptun" PASSED test_solar.py::test_four[neptun-1] PASSED test_solar.py::test_three[neptun-3] sun '3' "sun '3'" - "neptun" PASSED test_solar.py::test_four[neptun-3] PASSED test_solar.py::test_three[pluto-3] "sun '3'" - "pluto" PASSED test_solar.py::test_four[pluto-3] PASSED test_solar.py::test_three[neptun-4] sun '4' "sun '4'" - "neptun" PASSED test_solar.py::test_four[neptun-4] PASSED test_solar.py::test_three[pluto-4] "sun '4'" - "pluto" PASSED test_solar.py::test_four[pluto-4] PASSED test_solar.py::test_three[neptun-5] sun '5' "sun '5'" - "neptun" PASSED test_solar.py::test_four[neptun-5] PASSED test_solar.py::test_three[pluto-5] "sun '5'" - "pluto" PASSED test_solar.py::test_four[pluto-5] PASSED ``` The fact that "sun '1'" have been initialized twise is unexpected. From commits-noreply at bitbucket.org Thu Feb 19 12:42:28 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 19 Feb 2015 11:42:28 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: Merged in msabramo/pytest/remove_pdbpp_xfail (pull request #250) Message-ID: <20150219114228.17583.56790@app06.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/0ba56c3c5ef4/ Changeset: 0ba56c3c5ef4 User: hpk42 Date: 2015-02-19 11:42:23+00:00 Summary: Merged in msabramo/pytest/remove_pdbpp_xfail (pull request #250) Remove pdbpp xfails; don't seem necessary anymore Affected #: 2 files diff -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c -r 0ba56c3c5ef40dabe0693d2d743cdf2b887873ec testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -3,8 +3,6 @@ import pdb -xfail_if_pdbpp_installed = pytest.mark.xfail(hasattr(pdb, "__author__"), - reason="doctest/pdbpp problem: https://bitbucket.org/antocuni/pdb/issue/24/doctests-fail-when-pdbpp-is-installed", run=False) class TestDoctests: @@ -161,7 +159,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_external_and_issue116(self, testdir): p = testdir.mkpydir("hello") p.join("__init__.py").write(py.code.Source(""" @@ -201,7 +198,6 @@ "*test_txtfile_failing.txt:2: DocTestFailure" ]) - @xfail_if_pdbpp_installed def test_txtfile_with_fixtures(self, testdir): p = testdir.maketxtfile(""" >>> dir = getfixture('tmpdir') @@ -211,7 +207,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_txtfile_with_usefixtures_in_ini(self, testdir): testdir.makeini(""" [pytest] @@ -232,7 +227,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_with_fixtures(self, testdir): p = testdir.makepyfile(""" ''' @@ -244,7 +238,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_three_tests(self, testdir): p = testdir.makepyfile(""" ''' @@ -270,7 +263,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=3) - @xfail_if_pdbpp_installed def test_doctestmodule_two_tests_one_fail(self, testdir): p = testdir.makepyfile(""" class MyClass: diff -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c -r 0ba56c3c5ef40dabe0693d2d743cdf2b887873ec testing/test_pdb.py --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -2,7 +2,6 @@ import py import sys -from test_doctest import xfail_if_pdbpp_installed class TestPDB: def pytest_funcarg__pdblist(self, request): @@ -187,7 +186,6 @@ if child.isalive(): child.wait() - @xfail_if_pdbpp_installed def test_pdb_interaction_doctest(self, testdir): p1 = testdir.makepyfile(""" import pytest Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Thu Feb 19 12:42:28 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 19 Feb 2015 11:42:28 -0000 Subject: [Pytest-commit] commit/pytest: 3 new changesets Message-ID: <20150219114228.3793.10444@app03.ash-private.bitbucket.org> 3 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/08d9303d9afa/ Changeset: 08d9303d9afa Branch: remove_pdbpp_xfail User: msabramo Date: 2015-02-19 11:03:56+00:00 Summary: Remove pdbpp xfails; don't seem necessary anymore It seems that they're no longer necessary as the tests pass now [marca at marca-mac2 pytest]$ pip freeze backports.inspect==0.0.2 fancycompleter==0.4 funcsigs==0.2 ordereddict==1.1 -e hg+ssh://hg at bitbucket.org/antocuni/pdb at 4bda65ac8f8cc9b1850e0301669aac39200f2f9a#egg=pdbpp-fix_pytest_doctest_NoneType_object_has_no_attribute_lower py==1.4.26 Pygments==1.6 pyrepl==0.8.4 -e hg+ssh://hg at bitbucket.org/hpk42/pytest at 5fc366c50b56a94638c959be8456d2cb3c7e7c1c#egg=pytest-dev wmctrl==0.1 [marca at marca-mac2 pytest]$ py.test testing/test_doctest.py --tb=short ============================================================================= test session starts ============================================================================== platform darwin -- Python 2.7.9 -- py-1.4.26 -- pytest-2.7.0.dev1 collected 22 items testing/test_doctest.py ...................... ========================================================================== 22 passed in 1.61 seconds =========================================================================== See https://bitbucket.org/antocuni/pdb/issue/24/doctests-fail-when-pdbpp-is-installed Affected #: 1 file diff -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c -r 08d9303d9afa51a3c13d0300e7a11a5da406afc2 testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -3,8 +3,6 @@ import pdb -xfail_if_pdbpp_installed = pytest.mark.xfail(hasattr(pdb, "__author__"), - reason="doctest/pdbpp problem: https://bitbucket.org/antocuni/pdb/issue/24/doctests-fail-when-pdbpp-is-installed", run=False) class TestDoctests: @@ -161,7 +159,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_external_and_issue116(self, testdir): p = testdir.mkpydir("hello") p.join("__init__.py").write(py.code.Source(""" @@ -201,7 +198,6 @@ "*test_txtfile_failing.txt:2: DocTestFailure" ]) - @xfail_if_pdbpp_installed def test_txtfile_with_fixtures(self, testdir): p = testdir.maketxtfile(""" >>> dir = getfixture('tmpdir') @@ -211,7 +207,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_txtfile_with_usefixtures_in_ini(self, testdir): testdir.makeini(""" [pytest] @@ -232,7 +227,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_with_fixtures(self, testdir): p = testdir.makepyfile(""" ''' @@ -244,7 +238,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_three_tests(self, testdir): p = testdir.makepyfile(""" ''' @@ -270,7 +263,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=3) - @xfail_if_pdbpp_installed def test_doctestmodule_two_tests_one_fail(self, testdir): p = testdir.makepyfile(""" class MyClass: https://bitbucket.org/hpk42/pytest/commits/ed05c00ee11f/ Changeset: ed05c00ee11f Branch: remove_pdbpp_xfail User: msabramo Date: 2015-02-19 11:22:05+00:00 Summary: Remove xfail_if_pdbpp_installed from test_pdb.py Affected #: 1 file diff -r 08d9303d9afa51a3c13d0300e7a11a5da406afc2 -r ed05c00ee11f08a8e8418144680bf4d2d3a66af1 testing/test_pdb.py --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -2,7 +2,6 @@ import py import sys -from test_doctest import xfail_if_pdbpp_installed class TestPDB: def pytest_funcarg__pdblist(self, request): @@ -187,7 +186,6 @@ if child.isalive(): child.wait() - @xfail_if_pdbpp_installed def test_pdb_interaction_doctest(self, testdir): p1 = testdir.makepyfile(""" import pytest https://bitbucket.org/hpk42/pytest/commits/0ba56c3c5ef4/ Changeset: 0ba56c3c5ef4 User: hpk42 Date: 2015-02-19 11:42:23+00:00 Summary: Merged in msabramo/pytest/remove_pdbpp_xfail (pull request #250) Remove pdbpp xfails; don't seem necessary anymore Affected #: 2 files diff -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c -r 0ba56c3c5ef40dabe0693d2d743cdf2b887873ec testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -3,8 +3,6 @@ import pdb -xfail_if_pdbpp_installed = pytest.mark.xfail(hasattr(pdb, "__author__"), - reason="doctest/pdbpp problem: https://bitbucket.org/antocuni/pdb/issue/24/doctests-fail-when-pdbpp-is-installed", run=False) class TestDoctests: @@ -161,7 +159,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_external_and_issue116(self, testdir): p = testdir.mkpydir("hello") p.join("__init__.py").write(py.code.Source(""" @@ -201,7 +198,6 @@ "*test_txtfile_failing.txt:2: DocTestFailure" ]) - @xfail_if_pdbpp_installed def test_txtfile_with_fixtures(self, testdir): p = testdir.maketxtfile(""" >>> dir = getfixture('tmpdir') @@ -211,7 +207,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_txtfile_with_usefixtures_in_ini(self, testdir): testdir.makeini(""" [pytest] @@ -232,7 +227,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_with_fixtures(self, testdir): p = testdir.makepyfile(""" ''' @@ -244,7 +238,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_three_tests(self, testdir): p = testdir.makepyfile(""" ''' @@ -270,7 +263,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=3) - @xfail_if_pdbpp_installed def test_doctestmodule_two_tests_one_fail(self, testdir): p = testdir.makepyfile(""" class MyClass: diff -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c -r 0ba56c3c5ef40dabe0693d2d743cdf2b887873ec testing/test_pdb.py --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -2,7 +2,6 @@ import py import sys -from test_doctest import xfail_if_pdbpp_installed class TestPDB: def pytest_funcarg__pdblist(self, request): @@ -187,7 +186,6 @@ if child.isalive(): child.wait() - @xfail_if_pdbpp_installed def test_pdb_interaction_doctest(self, testdir): p1 = testdir.makepyfile(""" import pytest Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From issues-reply at bitbucket.org Thu Feb 19 16:03:57 2015 From: issues-reply at bitbucket.org (offbyone) Date: Thu, 19 Feb 2015 15:03:57 -0000 Subject: [Pytest-commit] Issue #217: Provide a host-based method of finding interpreters. (hpk42/tox) Message-ID: <20150219150357.14057.26793@app06.ash-private.bitbucket.org> New issue 217: Provide a host-based method of finding interpreters. https://bitbucket.org/hpk42/tox/issue/217/provide-a-host-based-method-of-finding offbyone: When running tox builds, I want to have tox find interpreters in a host-specific way; on some hosts, I have python 2.5 through 3.4 on the PATH, on other hosts those interpreters may or may not exist on my PATH, but might be found in pyenv directories, custom prefixes, or elsewhere. A standard on unix-ish hosts is ~/.config/.conf, for example, and maybe tox could use that: [interpreters] py25 = /home/me/local/bin/python2.5 ... From issues-reply at bitbucket.org Thu Feb 19 18:57:23 2015 From: issues-reply at bitbucket.org (pahaz) Date: Thu, 19 Feb 2015 17:57:23 -0000 Subject: [Pytest-commit] Issue #218: How can I add virtualenv --always-copy options? (hpk42/tox) Message-ID: <20150219175723.30811.90861@app11.ash-private.bitbucket.org> New issue 218: How can I add virtualenv --always-copy options? https://bitbucket.org/hpk42/tox/issue/218/how-can-i-add-virtualenv-always-copy pahaz: From commits-noreply at bitbucket.org Thu Feb 19 21:30:15 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 19 Feb 2015 20:30:15 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150219203015.26927.65735@app04.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/dfff965c16cb/ Changeset: dfff965c16cb Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-19 18:04:06+00:00 Summary: just copy in capturelog with minimal changes Affected #: 4 files diff -r bc2cf073d49b5eaa8a403c2e1409e98f450d2ea5 -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 _pytest/capture_log.py --- /dev/null +++ b/_pytest/capture_log.py @@ -0,0 +1,301 @@ +"""capture output of logging module. + +Installation +------------ + +The `pytest-capturelog`_ package may be installed with pip or easy_install:: + + pip install pytest-capturelog + easy_install pytest-capturelog + +.. _`pytest-capturelog`: http://pypi.python.org/pypi/pytest-capturelog/ + +Usage +----- + +If the plugin is installed log messages are captured by default and for +each failed test will be shown in the same manner as captured stdout and +stderr. + +Running without options:: + + py.test test_capturelog.py + +Shows failed tests like so:: + + -------------------------- Captured log --------------------------- + test_capturelog.py 26 INFO text going to logger + ------------------------- Captured stdout ------------------------- + text going to stdout + ------------------------- Captured stderr ------------------------- + text going to stderr + ==================== 2 failed in 0.02 seconds ===================== + +By default each captured log message shows the module, line number, +log level and message. Showing the exact module and line number is +useful for testing and debugging. If desired the log format and date +format can be specified to anything that the logging module supports. + +Running pytest specifying formatting options:: + + py.test \ + --log-format="%(asctime)s %(levelname)s %(message)s" \ + --log-date-format="%Y-%m-%d %H:%M:%S" test_capturelog.py + +Shows failed tests like so:: + + -------------------------- Captured log --------------------------- + 2010-04-10 14:48:44 INFO text going to logger + ------------------------- Captured stdout ------------------------- + text going to stdout + ------------------------- Captured stderr ------------------------- + text going to stderr + ==================== 2 failed in 0.02 seconds ===================== + +Further it is possible to disable capturing of logs completely with:: + + py.test --nocapturelog test_capturelog.py + +Shows failed tests in the normal manner as no logs were captured:: + + ------------------------- Captured stdout ------------------------- + text going to stdout + ------------------------- Captured stderr ------------------------- + text going to stderr + ==================== 2 failed in 0.02 seconds ===================== + +Inside tests it is possible to change the log level for the captured +log messages. This is supported by the ``caplog`` funcarg:: + + def test_foo(caplog): + caplog.setLevel(logging.INFO) + pass + +By default the level is set on the handler used to capture the log +messages, however as a convenience it is also possible to set the log +level of any logger:: + + def test_foo(caplog): + caplog.setLevel(logging.CRITICAL, logger='root.baz') + pass + +It is also possible to use a context manager to temporarily change the +log level:: + + def test_bar(caplog): + with caplog.atLevel(logging.INFO): + pass + +Again, by default the level of the handler is affected but the level +of any logger can be changed instead with:: + + def test_bar(caplog): + with caplog.atLevel(logging.CRITICAL, logger='root.baz'): + pass + +Lastly all the logs sent to the logger during the test run are made +available on the funcarg in the form of both the LogRecord instances +and the final log text. This is useful for when you want to assert on +the contents of a message:: + + def test_baz(caplog): + func_under_test() + for record in caplog.records(): + assert record.levelname != 'CRITICAL' + assert 'wally' not in caplog.text() + +For all the available attributes of the log records see the +``logging.LogRecord`` class. +""" + +import py +import logging + +LOG_FORMAT = '%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s' + + +def pytest_addoption(parser): + """Add options to control log capturing.""" + + group = parser.getgroup('capturelog', 'log capturing') + group.addoption('--nocapturelog', + dest='capturelog', + action='store_false', + default=True, + help='disable log capture') + group.addoption('--log-format', + dest='log_format', + default=LOG_FORMAT, + help='log format as used by the logging module') + group.addoption('--log-date-format', + dest='log_date_format', + default=None, + help='log date format as used by the logging module') + + +def pytest_configure(config): + """Activate log capturing if appropriate.""" + + if config.getvalue('capturelog'): + config.pluginmanager.register(CaptureLogPlugin(config), '_capturelog') + + +class CaptureLogPlugin(object): + """Attaches to the logging module and captures log messages for each test.""" + + def __init__(self, config): + """Creates a new plugin to capture log messges. + + The formatter can be safely shared across all handlers so + create a single one for the entire test session here. + """ + + self.formatter = logging.Formatter(config.getvalue('log_format'), + config.getvalue('log_date_format')) + + def pytest_runtest_setup(self, item): + """Start capturing log messages for this test. + + Creating a specific handler for each test ensures that we + avoid multi threading issues. + + Attaching the handler and setting the level at the beginning + of each test ensures that we are setup to capture log + messages. + """ + + # Create a handler for this test. + item.capturelog_handler = CaptureLogHandler() + item.capturelog_handler.setFormatter(self.formatter) + + # Attach the handler to the root logger and ensure that the + # root logger is set to log all levels. + root_logger = logging.getLogger() + root_logger.addHandler(item.capturelog_handler) + root_logger.setLevel(logging.NOTSET) + + def pytest_runtest_makereport(self, __multicall__, item, call): + """Add captured log messages for this report.""" + + report = __multicall__.execute() + + # This fn called after setup, call and teardown. Only + # interested in just after test call has finished. + if call.when == 'call': + + # Detach the handler from the root logger to ensure no + # further access to the handler. + root_logger = logging.getLogger() + root_logger.removeHandler(item.capturelog_handler) + + # For failed tests that have captured log messages add a + # captured log section to the report. + if not report.passed: + longrepr = getattr(report, 'longrepr', None) + if hasattr(longrepr, 'addsection'): + log = item.capturelog_handler.stream.getvalue().strip() + if log: + longrepr.addsection('Captured log', log) + + # Release the handler resources. + item.capturelog_handler.close() + del item.capturelog_handler + + return report + + +class CaptureLogHandler(logging.StreamHandler): + """A logging handler that stores log records and the log text.""" + + def __init__(self): + """Creates a new log handler.""" + + logging.StreamHandler.__init__(self) + self.stream = py.io.TextIO() + self.records = [] + + def close(self): + """Close this log handler and its underlying stream.""" + + logging.StreamHandler.close(self) + self.stream.close() + + def emit(self, record): + """Keep the log records in a list in addition to the log text.""" + + self.records.append(record) + logging.StreamHandler.emit(self, record) + + +class CaptureLogFuncArg(object): + """Provides access and control of log capturing.""" + + def __init__(self, handler): + """Creates a new funcarg.""" + + self.handler = handler + + def text(self): + """Returns the log text.""" + + return self.handler.stream.getvalue() + + def records(self): + """Returns the list of log records.""" + + return self.handler.records + + def setLevel(self, level, logger=None): + """Sets the level for capturing of logs. + + By default, the level is set on the handler used to capture + logs. Specify a logger name to instead set the level of any + logger. + """ + + obj = logger and logging.getLogger(logger) or self.handler + obj.setLevel(level) + + def atLevel(self, level, logger=None): + """Context manager that sets the level for capturing of logs. + + By default, the level is set on the handler used to capture + logs. Specify a logger name to instead set the level of any + logger. + """ + + obj = logger and logging.getLogger(logger) or self.handler + return CaptureLogLevel(obj, level) + + +class CaptureLogLevel(object): + """Context manager that sets the logging level of a handler or logger.""" + + def __init__(self, obj, level): + """Creates a new log level context manager.""" + + self.obj = obj + self.level = level + + def __enter__(self): + """Adjust the log level.""" + + self.orig_level = self.obj.level + self.obj.setLevel(self.level) + + def __exit__(self, exc_type, exc_value, traceback): + """Restore the log level.""" + + self.obj.setLevel(self.orig_level) + + +def pytest_funcarg__caplog(request): + """Returns a funcarg to access and control log capturing.""" + + return CaptureLogFuncArg(request._pyfuncitem.capturelog_handler) + + +def pytest_funcarg__capturelog(request): + """Returns a funcarg to access and control log capturing.""" + + return CaptureLogFuncArg(request._pyfuncitem.capturelog_handler) diff -r bc2cf073d49b5eaa8a403c2e1409e98f450d2ea5 -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -51,7 +51,7 @@ default_plugins = ( "mark main terminal runner python pdb unittest capture skipping " "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript " - "junitxml resultlog doctest cache").split() + "junitxml resultlog doctest cache capture_log").split() def _preloadplugins(): assert not _preinit diff -r bc2cf073d49b5eaa8a403c2e1409e98f450d2ea5 -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 testing/test_capture.py --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -337,6 +337,7 @@ # verify proper termination assert "closed" not in s + @pytest.mark.xfail(reason='logcapture integration') def test_logging_initialized_in_test(self, testdir): p = testdir.makepyfile(""" import sys diff -r bc2cf073d49b5eaa8a403c2e1409e98f450d2ea5 -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 testing/test_capturelog.py --- /dev/null +++ b/testing/test_capturelog.py @@ -0,0 +1,106 @@ +import py + +def test_nothing_logged(testdir): + testdir.makepyfile(''' + import sys + import logging + + + def test_foo(): + sys.stdout.write('text going to stdout') + sys.stderr.write('text going to stderr') + assert False + ''') + result = testdir.runpytest() + assert result.ret == 1 + result.stdout.fnmatch_lines(['* Captured stdout *', 'text going to stdout']) + result.stdout.fnmatch_lines(['* Captured stderr *', 'text going to stderr']) + py.test.raises(Exception, result.stdout.fnmatch_lines, ['* Captured log *']) + +def test_messages_logged(testdir): + testdir.makepyfile(''' + import sys + import logging + + + def test_foo(): + sys.stdout.write('text going to stdout') + sys.stderr.write('text going to stderr') + logging.getLogger().info('text going to logger') + assert False + ''') + result = testdir.runpytest() + assert result.ret == 1 + result.stdout.fnmatch_lines(['* Captured log *', '*text going to logger*']) + result.stdout.fnmatch_lines(['* Captured stdout *', 'text going to stdout']) + result.stdout.fnmatch_lines(['* Captured stderr *', 'text going to stderr']) + +def test_change_level(testdir): + testdir.makepyfile(''' + import sys + import logging + + + def test_foo(caplog): + caplog.setLevel(logging.INFO) + log = logging.getLogger() + log.debug('handler DEBUG level') + log.info('handler INFO level') + + caplog.setLevel(logging.CRITICAL, logger='root.baz') + log = logging.getLogger('root.baz') + log.warning('logger WARNING level') + log.critical('logger CRITICAL level') + + assert False + ''') + result = testdir.runpytest() + assert result.ret == 1 + result.stdout.fnmatch_lines(['* Captured log *', '*handler INFO level*', '*logger CRITICAL level*']) + py.test.raises(Exception, result.stdout.fnmatch_lines, ['* Captured log *', '*handler DEBUG level*']) + py.test.raises(Exception, result.stdout.fnmatch_lines, ['* Captured log *', '*logger WARNING level*']) + +def test_with_statement(testdir): + testdir.makepyfile(''' + from __future__ import with_statement + import sys + import logging + + + def test_foo(caplog): + with caplog.atLevel(logging.INFO): + log = logging.getLogger() + log.debug('handler DEBUG level') + log.info('handler INFO level') + + with caplog.atLevel(logging.CRITICAL, logger='root.baz'): + log = logging.getLogger('root.baz') + log.warning('logger WARNING level') + log.critical('logger CRITICAL level') + + assert False + ''') + result = testdir.runpytest() + assert result.ret == 1 + result.stdout.fnmatch_lines(['* Captured log *', '*handler INFO level*', '*logger CRITICAL level*']) + py.test.raises(Exception, result.stdout.fnmatch_lines, ['* Captured log *', '*handler DEBUG level*']) + py.test.raises(Exception, result.stdout.fnmatch_lines, ['* Captured log *', '*logger WARNING level*']) + +def test_log_access(testdir): + testdir.makepyfile(''' + import sys + import logging + + + def test_foo(caplog): + logging.getLogger().info('boo %s', 'arg') + assert caplog.records()[0].levelname == 'INFO' + assert caplog.records()[0].msg == 'boo %s' + assert 'boo arg' in caplog.text() + ''') + result = testdir.runpytest() + assert result.ret == 0 + +def test_funcarg_help(testdir): + result = testdir.runpytest('--funcargs') + result.stdout.fnmatch_lines(['*caplog*']) https://bitbucket.org/hpk42/pytest/commits/8211b20606ae/ Changeset: 8211b20606ae Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-19 20:29:52+00:00 Summary: ignore the pytest-cache/capturelog distributions and fix related tests Affected #: 4 files diff -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 -r 8211b20606ae19bc1b71144e623c9bd5964773f2 _pytest/core.py --- a/_pytest/core.py +++ b/_pytest/core.py @@ -10,7 +10,11 @@ assert py.__version__.split(".")[:2] >= ['1', '4'], ("installation problem: " "%s is too old, remove or upgrade 'py'" % (py.__version__)) -py3 = sys.version_info > (3,0) +py3 = sys.version_info > (3, 0) + +# +_ALREADY_INCLUDED_PLUGINS = 'pytest-cache', 'pytest-capturelog' + class TagTracer: def __init__(self): @@ -269,6 +273,11 @@ except ImportError: return # XXX issue a warning for ep in iter_entry_points('pytest11'): + project_name = getattr(ep.dist, 'project_name', None) + if project_name in _ALREADY_INCLUDED_PLUGINS: + self._warnings.append( + 'ignoring now included plugin ' + project_name) + continue name = ep.name if name.startswith("pytest_"): name = name[7:] diff -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 -r 8211b20606ae19bc1b71144e623c9bd5964773f2 testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -307,6 +307,7 @@ assert name == "pytest11" class EntryPoint: name = "mytestplugin" + dist = None def load(self): assert 0, "should not arrive here" return iter([EntryPoint()]) diff -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 -r 8211b20606ae19bc1b71144e623c9bd5964773f2 testing/test_core.py --- a/testing/test_core.py +++ b/testing/test_core.py @@ -70,12 +70,13 @@ assert name == "pytest11" class EntryPoint: name = "pytest_mytestplugin" - dist = None + class dist: + name = None def load(self): class PseudoPlugin: x = 42 return PseudoPlugin() - return iter([EntryPoint()]) + yield EntryPoint() monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) pluginmanager = PluginManager() @@ -83,6 +84,28 @@ plugin = pluginmanager.getplugin("mytestplugin") assert plugin.x == 42 + @pytest.mark.parametrize('distname', ['pytest-cache', 'pytest-capturelog']) + def test_dont_consider_setuptools_included(self, distname, monkeypatch): + pkg_resources = pytest.importorskip("pkg_resources") + def my_iter(name): + assert name == "pytest11" + class EntryPoint: + name = "pytest_mytestplugin" + class dist: + project_name = distname + def load(self): + class PseudoPlugin: + x = 42 + return PseudoPlugin() + yield EntryPoint() + + monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) + pluginmanager = PluginManager() + pluginmanager.consider_setuptools_entrypoints() + plugin = pluginmanager.getplugin("mytestplugin") + assert plugin is None + + def test_consider_setuptools_not_installed(self, monkeypatch): monkeypatch.setitem(py.std.sys.modules, 'pkg_resources', py.std.types.ModuleType("pkg_resources")) diff -r dfff965c16cb8ad509b0cd16e2930081d628dbc1 -r 8211b20606ae19bc1b71144e623c9bd5964773f2 tox.ini --- a/tox.ini +++ b/tox.ini @@ -15,8 +15,9 @@ [testenv:flakes] changedir= -deps = pytest-flakes>=0.2 -commands = py.test --flakes -m flakes _pytest testing +deps = flake8 + mccabe +commands = pytest.py _pytest testing [testenv:py27-xdist] changedir=. @@ -141,5 +142,8 @@ python_files=test_*.py *_test.py testing/*/*.py python_classes=Test Acceptance python_functions=test -pep8ignore = E401 E225 E261 E128 E124 E302 norecursedirs = .tox ja .hg + + +[flake8] +ignore = E401 E225 E261 E128 E124 E302 Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Thu Feb 19 21:42:25 2015 From: builds at drone.io (Drone.io Build) Date: Thu, 19 Feb 2015 20:42:25 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 372 Message-ID: <20150219204218.3877.98713@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/372 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3852:8211b20606ae Author : Ronny Pfannschmidt Branch : copy-in-cache Message: ignore the pytest-cache/capturelog distributions and fix related tests -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Thu Feb 19 22:25:06 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 19 Feb 2015 21:25:06 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: finish backward compat for looponfail Message-ID: <20150219212506.15993.50204@app11.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/7c39287ab3d0/ Changeset: 7c39287ab3d0 Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-19 21:05:29+00:00 Summary: finish backward compat for looponfail Affected #: 2 files diff -r 8211b20606ae19bc1b71144e623c9bd5964773f2 -r 7c39287ab3d0b487a74f38930df27de1f17ade08 _pytest/cache.py --- a/_pytest/cache.py +++ b/_pytest/cache.py @@ -1,7 +1,8 @@ import py import pytest import json - +import sys +import pkg_resources class Cache: def __init__(self, config): @@ -114,11 +115,11 @@ yield p -import py -import pytest - def pytest_addoption(parser): + outside_looponfail = 'xdist' in sys.modules and \ + 'looponfail.py' in pkg_resources.resource_listdir('xdist', '.') + group = parser.getgroup("general") group.addoption( '--lf', action='store_true', dest="lf", @@ -136,9 +137,10 @@ group.addoption( '--looponchange', action='store_true', dest='looponchange', help='rerun every time the workdir changes') - group.addoption( - '--looponfail', action='store_true', dest='looponfail', - help='rerun every time the workdir changes') + if not outside_looponfail: + group._addoption( + '-f', '--looponfail', action='store_true', dest='looponfail', + help='rerun every time the workdir changes') parser.addini( "looponchangeroots", type="pathlist", help="directories to check for changes", default=[py.path.local()]) diff -r 8211b20606ae19bc1b71144e623c9bd5964773f2 -r 7c39287ab3d0b487a74f38930df27de1f17ade08 _pytest/onchange.py --- a/_pytest/onchange.py +++ b/_pytest/onchange.py @@ -9,12 +9,16 @@ def looponchange(config): newargs = config._origargs[:] - newargs.remove('--looponchange') + if '--looponchange' in newargs: + newargs.remove('--looponchange') + else: + newargs.remove('-f') stats = StatRecorder(config.getini('looponchangeroots')) command = py.std.functools.partial( py.std.subprocess.call, [ py.std.sys.executable, '-c', SCRIPT % newargs]) + command() loop_forever(stats, command) return 2 Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Thu Feb 19 22:33:26 2015 From: builds at drone.io (Drone.io Build) Date: Thu, 19 Feb 2015 21:33:26 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 373 Message-ID: <20150219213326.4040.13954@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/373 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3853:7c39287ab3d0 Author : Ronny Pfannschmidt Branch : copy-in-cache Message: finish backward compat for looponfail -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Thu Feb 19 22:58:21 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 19 Feb 2015 21:58:21 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: use hook wrapping to separate logging for test, call, teardown Message-ID: <20150219215821.4822.68545@app07.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/c321b799400d/ Changeset: c321b799400d Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-19 21:58:11+00:00 Summary: use hook wrapping to separate logging for test, call, teardown Affected #: 3 files diff -r 7c39287ab3d0b487a74f38930df27de1f17ade08 -r c321b799400db373e4f10b50cb6cb43961109c23 _pytest/cache.py --- a/_pytest/cache.py +++ b/_pytest/cache.py @@ -117,8 +117,12 @@ def pytest_addoption(parser): - outside_looponfail = 'xdist' in sys.modules and \ - 'looponfail.py' in pkg_resources.resource_listdir('xdist', '.') + try: + ls = pkg_resources.resource_listdir('xdist', '.') + except: + outside_looponfail = False + else: + outside_looponfail = 'looponfail.py' in ls group = parser.getgroup("general") group.addoption( diff -r 7c39287ab3d0b487a74f38930df27de1f17ade08 -r c321b799400db373e4f10b50cb6cb43961109c23 _pytest/capture_log.py --- a/_pytest/capture_log.py +++ b/_pytest/capture_log.py @@ -110,6 +110,7 @@ import py import logging +import pytest LOG_FORMAT = '%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s' @@ -137,7 +138,7 @@ """Activate log capturing if appropriate.""" if config.getvalue('capturelog'): - config.pluginmanager.register(CaptureLogPlugin(config), '_capturelog') + config.pluginmanager.register(CaptureLogPlugin(config), 'capturelog') class CaptureLogPlugin(object): @@ -153,6 +154,7 @@ self.formatter = logging.Formatter(config.getvalue('log_format'), config.getvalue('log_date_format')) + @pytest.mark.hookwrapper def pytest_runtest_setup(self, item): """Start capturing log messages for this test. @@ -173,6 +175,11 @@ root_logger = logging.getLogger() root_logger.addHandler(item.capturelog_handler) root_logger.setLevel(logging.NOTSET) + yield + item.capturelog_handler.close() + root_logger.removeHandler(item.capturelog_handler) + + pytest_runtest_teardown = pytest_runtest_call = pytest_runtest_setup def pytest_runtest_makereport(self, __multicall__, item, call): """Add captured log messages for this report.""" @@ -182,23 +189,11 @@ # This fn called after setup, call and teardown. Only # interested in just after test call has finished. if call.when == 'call': - - # Detach the handler from the root logger to ensure no - # further access to the handler. - root_logger = logging.getLogger() - root_logger.removeHandler(item.capturelog_handler) - - # For failed tests that have captured log messages add a - # captured log section to the report. - if not report.passed: - longrepr = getattr(report, 'longrepr', None) - if hasattr(longrepr, 'addsection'): - log = item.capturelog_handler.stream.getvalue().strip() - if log: - longrepr.addsection('Captured log', log) - - # Release the handler resources. - item.capturelog_handler.close() + longrepr = getattr(report, 'longrepr', None) + if hasattr(longrepr, 'addsection'): + log = item.capturelog_handler.value.strip() + if log: + report.sections.append(('Captured log ' + call.when, log)) del item.capturelog_handler return report @@ -212,11 +207,19 @@ logging.StreamHandler.__init__(self) self.stream = py.io.TextIO() - self.records = [] + self.records = [] + self._value = None + + @property + def value(self): + if self._value is None: + return self.stream.getvalue() + else: + return self._value def close(self): """Close this log handler and its underlying stream.""" - + self._value = self.stream.getvalue() logging.StreamHandler.close(self) self.stream.close() @@ -230,15 +233,19 @@ class CaptureLogFuncArg(object): """Provides access and control of log capturing.""" - def __init__(self, handler): + def __init__(self, node): """Creates a new funcarg.""" - self.handler = handler + self.node = node + + @property + def handler(self): + return self.node.capturelog_handler def text(self): """Returns the log text.""" - return self.handler.stream.getvalue() + return self.handler.value def records(self): """Returns the list of log records.""" @@ -288,14 +295,8 @@ self.obj.setLevel(self.orig_level) - -def pytest_funcarg__caplog(request): + at pytest.fixture +def caplog(request): """Returns a funcarg to access and control log capturing.""" - return CaptureLogFuncArg(request._pyfuncitem.capturelog_handler) - - -def pytest_funcarg__capturelog(request): - """Returns a funcarg to access and control log capturing.""" - - return CaptureLogFuncArg(request._pyfuncitem.capturelog_handler) + return CaptureLogFuncArg(request.node) diff -r 7c39287ab3d0b487a74f38930df27de1f17ade08 -r c321b799400db373e4f10b50cb6cb43961109c23 _pytest/onchange.py --- a/_pytest/onchange.py +++ b/_pytest/onchange.py @@ -1,5 +1,5 @@ import py - +import subprocess SCRIPT = """ import pytest @@ -7,6 +7,14 @@ """ +def run_once(args, tw=None): + tw = py.io.TerminalWriter() + subprocess.call(args) + tw.line() + tw.sep('#', 'waiting for changes') + tw.line() + + def looponchange(config): newargs = config._origargs[:] if '--looponchange' in newargs: @@ -14,10 +22,8 @@ else: newargs.remove('-f') stats = StatRecorder(config.getini('looponchangeroots')) - command = py.std.functools.partial( - py.std.subprocess.call, [ - py.std.sys.executable, - '-c', SCRIPT % newargs]) + command = py.std.functools.partial(run_once, [ + py.std.sys.executable, '-c', SCRIPT % newargs]) command() loop_forever(stats, command) return 2 Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Thu Feb 19 23:00:43 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 19 Feb 2015 22:00:43 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: universal wheel Message-ID: <20150219220043.32738.1148@app12.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/3104f1e16689/ Changeset: 3104f1e16689 Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-19 22:00:29+00:00 Summary: universal wheel Affected #: 1 file diff -r c321b799400db373e4f10b50cb6cb43961109c23 -r 3104f1e166897ef1977fa8be67915e33949a93a5 setup.cfg --- a/setup.cfg +++ b/setup.cfg @@ -3,6 +3,9 @@ build-dir = doc/build all_files = 1 +[wheel] +universal = 1 + [upload_sphinx] upload-dir = doc/en/build/html Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Thu Feb 19 23:08:00 2015 From: builds at drone.io (Drone.io Build) Date: Thu, 19 Feb 2015 22:08:00 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 374 Message-ID: <20150219220800.4020.72946@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/374 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3854:c321b799400d Author : Ronny Pfannschmidt Branch : copy-in-cache Message: use hook wrapping to separate logging for test, call, teardown -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Thu Feb 19 23:15:45 2015 From: builds at drone.io (Drone.io Build) Date: Thu, 19 Feb 2015 22:15:45 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 375 Message-ID: <20150219221534.109573.96431@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/375 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3855:3104f1e16689 Author : Ronny Pfannschmidt Branch : copy-in-cache Message: universal wheel -------------- next part -------------- An HTML attachment was scrubbed... URL: From issues-reply at bitbucket.org Thu Feb 19 23:48:31 2015 From: issues-reply at bitbucket.org (Ronny Pfannschmidt) Date: Thu, 19 Feb 2015 22:48:31 -0000 Subject: [Pytest-commit] Issue #219: devenv section and a devenv subcommand (hpk42/tox) Message-ID: <20150219224831.11425.21385@app08.ash-private.bitbucket.org> New issue 219: devenv section and a devenv subcommand https://bitbucket.org/hpk42/tox/issue/219/devenv-section-and-a-devenv-subcommand Ronny Pfannschmidt: tox is fabulous at creating environments, it should also create the one a developer will use for development in order to steamline that From commits-noreply at bitbucket.org Sat Feb 21 20:11:29 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 19:11:29 -0000 Subject: [Pytest-commit] commit/tox: 2 new changesets Message-ID: <20150221191129.26232.40828@app10.ash-private.bitbucket.org> 2 new commits in tox: https://bitbucket.org/hpk42/tox/commits/9383ae57a773/ Changeset: 9383ae57a773 Branch: add-py35 User: tseaver Date: 2015-02-16 15:23:31+00:00 Summary: Add support for 'py35' -> 'python3.5'. Affected #: 2 files diff -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e -r 9383ae57a773b21a35217f9ce8d2fa2f9181d5b0 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -18,7 +18,7 @@ default_factors = {'jython': 'jython', 'pypy': 'pypy', 'pypy3': 'pypy3', 'py': sys.executable} -for version in '24,25,26,27,30,31,32,33,34'.split(','): +for version in '24,25,26,27,30,31,32,33,34,35'.split(','): default_factors['py' + version] = 'python%s.%s' % tuple(version) def parseconfig(args=None, pkg=None): diff -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e -r 9383ae57a773b21a35217f9ce8d2fa2f9181d5b0 tox/_quickstart.py --- a/tox/_quickstart.py +++ b/tox/_quickstart.py @@ -56,7 +56,7 @@ term_input = input -all_envs = ['py26', 'py27', 'py32', 'py33', 'py34', 'pypy', 'jython'] +all_envs = ['py26', 'py27', 'py32', 'py33', 'py34', 'py35', 'pypy', 'jython'] PROMPT_PREFIX = '> ' https://bitbucket.org/hpk42/tox/commits/87d02c331675/ Changeset: 87d02c331675 User: hpk42 Date: 2015-02-21 19:11:26+00:00 Summary: Merged in tseaver/tox/add-py35 (pull request #134) Add support for 'py35' -> 'python3.5'. Affected #: 2 files diff -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -18,7 +18,7 @@ default_factors = {'jython': 'jython', 'pypy': 'pypy', 'pypy3': 'pypy3', 'py': sys.executable} -for version in '24,25,26,27,30,31,32,33,34'.split(','): +for version in '24,25,26,27,30,31,32,33,34,35'.split(','): default_factors['py' + version] = 'python%s.%s' % tuple(version) def parseconfig(args=None, pkg=None): diff -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 tox/_quickstart.py --- a/tox/_quickstart.py +++ b/tox/_quickstart.py @@ -56,7 +56,7 @@ term_input = input -all_envs = ['py26', 'py27', 'py32', 'py33', 'py34', 'pypy', 'jython'] +all_envs = ['py26', 'py27', 'py32', 'py33', 'py34', 'py35', 'pypy', 'jython'] PROMPT_PREFIX = '> ' Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 21 20:11:29 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 19:11:29 -0000 Subject: [Pytest-commit] commit/tox: hpk42: Merged in tseaver/tox/add-py35 (pull request #134) Message-ID: <20150221191129.3813.79450@app13.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/87d02c331675/ Changeset: 87d02c331675 User: hpk42 Date: 2015-02-21 19:11:26+00:00 Summary: Merged in tseaver/tox/add-py35 (pull request #134) Add support for 'py35' -> 'python3.5'. Affected #: 2 files diff -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -18,7 +18,7 @@ default_factors = {'jython': 'jython', 'pypy': 'pypy', 'pypy3': 'pypy3', 'py': sys.executable} -for version in '24,25,26,27,30,31,32,33,34'.split(','): +for version in '24,25,26,27,30,31,32,33,34,35'.split(','): default_factors['py' + version] = 'python%s.%s' % tuple(version) def parseconfig(args=None, pkg=None): diff -r e2be096eb1c19a2d1df5b6d80932e6d862dd8f7e -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 tox/_quickstart.py --- a/tox/_quickstart.py +++ b/tox/_quickstart.py @@ -56,7 +56,7 @@ term_input = input -all_envs = ['py26', 'py27', 'py32', 'py33', 'py34', 'pypy', 'jython'] +all_envs = ['py26', 'py27', 'py32', 'py33', 'py34', 'py35', 'pypy', 'jython'] PROMPT_PREFIX = '> ' Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 21 20:18:19 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 19:18:19 -0000 Subject: [Pytest-commit] commit/tox: hpk42: Merged in mhirota/tox (pull request #133) Message-ID: <20150221191819.26434.48313@app13.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/4298877e4216/ Changeset: 4298877e4216 User: hpk42 Date: 2015-02-21 19:18:16+00:00 Summary: Merged in mhirota/tox (pull request #133) Fix issue #124 Affected #: 6 files diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,9 @@ - fix issue11: add a ``skip_install`` per-testenv setting which prevents the installation of a package. Thanks Julian Krause. +- fix issue124: ignore command exit codes; when a command has a "-" prefix, + tox will ignore the exit code of that command + 1.8.1 ----------- diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -30,3 +30,4 @@ Marc Schlaich Clark Boylan Eugene Yunak +Mark Hirota diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -86,6 +86,8 @@ will be appended (and may contain another ``\`` character ...). For eventually performing a call to ``subprocess.Popen(args, ...)`` ``args`` are determined by splitting the whole command by whitespace. + Similar to ``make`` recipe lines, any command with a leading ``-`` + will ignore the exit code. .. confval:: install_command=ARGV diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 doc/example/basic.txt --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -244,3 +244,19 @@ python setup.py test -a "-epy27" is equivalent to running ``tox -epy27``. + +Ignoring a command exit code +---------------------------- + +In some cases, you may want to ignore a command exit code. For example:: + + [testenv:py27] + commands = coverage erase + {envbindir}/python setup.py develop + coverage run -p setup.py test + coverage combine + - coverage html + {envbindir}/flake8 loads + +By using the ``-`` prefix, similar to a ``make`` recipe line, you can ignore +the exit code for that command. diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -79,7 +79,7 @@ f.flush() return f - def popen(self, args, cwd=None, env=None, redirect=True, returnout=False): + def popen(self, args, cwd=None, env=None, redirect=True, returnout=False, ignore_ret=False): stdout = outpath = None resultjson = self.session.config.option.resultjson if resultjson or redirect: @@ -141,7 +141,7 @@ ret = popen.wait() finally: self._popenlist.remove(popen) - if ret: + if ret and not ignore_ret: invoked = " ".join(map(str, popen.args)) if outpath: self.report.error("invocation failed (exit code %d), logfile: %s" % diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 tox/_venv.py --- a/tox/_venv.py +++ b/tox/_venv.py @@ -345,8 +345,19 @@ message = "commands[%s] | %s" % (i, ' '.join( [str(x) for x in argv])) action.setactivity("runtests", message) + # check to see if we need to ignore the return code + # if so, we need to alter the command line arguments + if argv[0].startswith("-"): + ignore_ret = True + if argv[0] == "-": + del argv[0] + else: + argv[0] = argv[0].lstrip("-") + else: + ignore_ret = False + try: - self._pcall(argv, cwd=cwd, action=action, redirect=redirect) + self._pcall(argv, cwd=cwd, action=action, redirect=redirect, ignore_ret=ignore_ret) except tox.exception.InvocationError: val = sys.exc_info()[1] self.session.report.error(str(val)) @@ -357,7 +368,7 @@ raise def _pcall(self, args, venv=True, cwd=None, extraenv={}, - action=None, redirect=True): + action=None, redirect=True, ignore_ret=False): for name in ("VIRTUALENV_PYTHON", "PYTHONDONTWRITEBYTECODE"): try: del os.environ[name] @@ -369,7 +380,7 @@ try: args[0] = self.getcommandpath(args[0], venv, cwd) env = self._getenv(extraenv) - return action.popen(args, cwd=cwd, env=env, redirect=redirect) + return action.popen(args, cwd=cwd, env=env, redirect=redirect, ignore_ret=ignore_ret) finally: os.environ['PATH'] = old Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 21 20:18:19 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 19:18:19 -0000 Subject: [Pytest-commit] commit/tox: 4 new changesets Message-ID: <20150221191819.21795.66587@app14.ash-private.bitbucket.org> 4 new commits in tox: https://bitbucket.org/hpk42/tox/commits/dcecf02917cf/ Changeset: dcecf02917cf User: Mark Hirota Date: 2015-02-10 00:30:00+00:00 Summary: Fix issue #124 Affected #: 4 files diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r dcecf02917cfdfc681b00f2c8eeb2193ad283617 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,9 @@ - echo output to stdout when ``--report-json`` is used +- fix issue124: ignore command exit codes; when a command has a "-" prefix, + tox will ignore the exit code of that command + 1.8.1 ----------- diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r dcecf02917cfdfc681b00f2c8eeb2193ad283617 CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -29,3 +29,4 @@ Marc Schlaich Clark Boylan Eugene Yunak +Mark Hirota diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r dcecf02917cfdfc681b00f2c8eeb2193ad283617 tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -79,7 +79,7 @@ f.flush() return f - def popen(self, args, cwd=None, env=None, redirect=True, returnout=False): + def popen(self, args, cwd=None, env=None, redirect=True, returnout=False, ignore_ret=False): stdout = outpath = None resultjson = self.session.config.option.resultjson if resultjson or redirect: @@ -141,7 +141,7 @@ ret = popen.wait() finally: self._popenlist.remove(popen) - if ret: + if ret and not ignore_ret: invoked = " ".join(map(str, popen.args)) if outpath: self.report.error("invocation failed (exit code %d), logfile: %s" % diff -r 27b8bdcddd6a197ad600afac03a1e3fb61cc6a5b -r dcecf02917cfdfc681b00f2c8eeb2193ad283617 tox/_venv.py --- a/tox/_venv.py +++ b/tox/_venv.py @@ -345,8 +345,19 @@ message = "commands[%s] | %s" % (i, ' '.join( [str(x) for x in argv])) action.setactivity("runtests", message) + # check to see if we need to ignore the return code + # if so, we need to alter the command line arguments + if argv[0].startswith("-"): + ignore_ret = True + if argv[0] == "-": + del argv[0] + else: + argv[0] = argv[0].lstrip("-") + else: + ignore_ret = False + try: - self._pcall(argv, cwd=cwd, action=action, redirect=redirect) + self._pcall(argv, cwd=cwd, action=action, redirect=redirect, ignore_ret=ignore_ret) except tox.exception.InvocationError: val = sys.exc_info()[1] self.session.report.error(str(val)) @@ -357,7 +368,7 @@ raise def _pcall(self, args, venv=True, cwd=None, extraenv={}, - action=None, redirect=True): + action=None, redirect=True, ignore_ret=False): for name in ("VIRTUALENV_PYTHON", "PYTHONDONTWRITEBYTECODE"): try: del os.environ[name] @@ -369,7 +380,7 @@ try: args[0] = self.getcommandpath(args[0], venv, cwd) env = self._getenv(extraenv) - return action.popen(args, cwd=cwd, env=env, redirect=redirect) + return action.popen(args, cwd=cwd, env=env, redirect=redirect, ignore_ret=ignore_ret) finally: os.environ['PATH'] = old https://bitbucket.org/hpk42/tox/commits/e63209744ef1/ Changeset: e63209744ef1 User: Mark Hirota Date: 2015-02-11 19:11:54+00:00 Summary: Update doc files for issue #124 fix Affected #: 2 files diff -r dcecf02917cfdfc681b00f2c8eeb2193ad283617 -r e63209744ef18938575a274cd6527ea687106305 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -86,6 +86,8 @@ will be appended (and may contain another ``\`` character ...). For eventually performing a call to ``subprocess.Popen(args, ...)`` ``args`` are determined by splitting the whole command by whitespace. + Similar to ``make`` recipe lines, any command with a leading ``-`` + will ignore the exit code. .. confval:: install_command=ARGV diff -r dcecf02917cfdfc681b00f2c8eeb2193ad283617 -r e63209744ef18938575a274cd6527ea687106305 doc/example/basic.txt --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -244,3 +244,19 @@ python setup.py test -a "-epy27" is equivalent to running ``tox -epy27``. + +Ignoring a command exit code +---------------------------- + +In some cases, you may want to ignore a command exit code. For example:: + + [testenv:py27] + commands = coverage erase + {envbindir}/python setup.py develop + coverage run -p setup.py test + coverage combine + - coverage html + {envbindir}/flake8 loads + +By using the ``-`` prefix, similar to a ``make`` recipe line, you can ignore +the exit code for that command. https://bitbucket.org/hpk42/tox/commits/81c1e121afbf/ Changeset: 81c1e121afbf User: Mark Hirota Date: 2015-02-11 19:35:56+00:00 Summary: Merged hpk42/tox into default; Resolved conflict in CHANGELOG Affected #: 5 files diff -r e63209744ef18938575a274cd6527ea687106305 -r 81c1e121afbf2ee910d110e16c26ac892fdce16c CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,9 @@ - echo output to stdout when ``--report-json`` is used +- fix issue11: add a ``skip_install`` per-testenv setting which + prevents the installation of a package. Thanks Julian Krause. + - fix issue124: ignore command exit codes; when a command has a "-" prefix, tox will ignore the exit code of that command diff -r e63209744ef18938575a274cd6527ea687106305 -r 81c1e121afbf2ee910d110e16c26ac892fdce16c CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -24,6 +24,7 @@ Mattieu Agopian Asmund Grammeltwedt Ionel Maries Cristian +Julian Krause Alexandre Conrad Morgan Fainberg Marc Schlaich diff -r e63209744ef18938575a274cd6527ea687106305 -r 81c1e121afbf2ee910d110e16c26ac892fdce16c doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -254,6 +254,16 @@ **default**: ``False`` +.. confval:: skip_install=BOOL + + .. versionadded:: 1.9 + + Do not install the current package. This can be used when you need the + virtualenv management but do not want to install the current package + into that environment. + + **default**: ``False`` + Substitutions ------------- diff -r e63209744ef18938575a274cd6527ea687106305 -r 81c1e121afbf2ee910d110e16c26ac892fdce16c tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -474,7 +474,7 @@ if self.setupenv(venv): if venv.envconfig.develop: self.developpkg(venv, self.config.setupdir) - elif self.config.skipsdist: + elif self.config.skipsdist or venv.envconfig.skip_install: self.finishvenv(venv) else: self.installpkg(venv, sdist_path) diff -r e63209744ef18938575a274cd6527ea687106305 -r 81c1e121afbf2ee910d110e16c26ac892fdce16c tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -395,6 +395,8 @@ vc.pip_pre = config.option.pre or reader.getbool( section, "pip_pre", False) + vc.skip_install = reader.getbool(section, "skip_install", False) + return vc def _getenvdata(self, reader, toxsection): https://bitbucket.org/hpk42/tox/commits/4298877e4216/ Changeset: 4298877e4216 User: hpk42 Date: 2015-02-21 19:18:16+00:00 Summary: Merged in mhirota/tox (pull request #133) Fix issue #124 Affected #: 6 files diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,9 @@ - fix issue11: add a ``skip_install`` per-testenv setting which prevents the installation of a package. Thanks Julian Krause. +- fix issue124: ignore command exit codes; when a command has a "-" prefix, + tox will ignore the exit code of that command + 1.8.1 ----------- diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 CONTRIBUTORS --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -30,3 +30,4 @@ Marc Schlaich Clark Boylan Eugene Yunak +Mark Hirota diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -86,6 +86,8 @@ will be appended (and may contain another ``\`` character ...). For eventually performing a call to ``subprocess.Popen(args, ...)`` ``args`` are determined by splitting the whole command by whitespace. + Similar to ``make`` recipe lines, any command with a leading ``-`` + will ignore the exit code. .. confval:: install_command=ARGV diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 doc/example/basic.txt --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -244,3 +244,19 @@ python setup.py test -a "-epy27" is equivalent to running ``tox -epy27``. + +Ignoring a command exit code +---------------------------- + +In some cases, you may want to ignore a command exit code. For example:: + + [testenv:py27] + commands = coverage erase + {envbindir}/python setup.py develop + coverage run -p setup.py test + coverage combine + - coverage html + {envbindir}/flake8 loads + +By using the ``-`` prefix, similar to a ``make`` recipe line, you can ignore +the exit code for that command. diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 tox/_cmdline.py --- a/tox/_cmdline.py +++ b/tox/_cmdline.py @@ -79,7 +79,7 @@ f.flush() return f - def popen(self, args, cwd=None, env=None, redirect=True, returnout=False): + def popen(self, args, cwd=None, env=None, redirect=True, returnout=False, ignore_ret=False): stdout = outpath = None resultjson = self.session.config.option.resultjson if resultjson or redirect: @@ -141,7 +141,7 @@ ret = popen.wait() finally: self._popenlist.remove(popen) - if ret: + if ret and not ignore_ret: invoked = " ".join(map(str, popen.args)) if outpath: self.report.error("invocation failed (exit code %d), logfile: %s" % diff -r 87d02c331675117c9104739fcff2ff0e8d10c3e6 -r 4298877e42165fcc80bccd1cc809583f8178c301 tox/_venv.py --- a/tox/_venv.py +++ b/tox/_venv.py @@ -345,8 +345,19 @@ message = "commands[%s] | %s" % (i, ' '.join( [str(x) for x in argv])) action.setactivity("runtests", message) + # check to see if we need to ignore the return code + # if so, we need to alter the command line arguments + if argv[0].startswith("-"): + ignore_ret = True + if argv[0] == "-": + del argv[0] + else: + argv[0] = argv[0].lstrip("-") + else: + ignore_ret = False + try: - self._pcall(argv, cwd=cwd, action=action, redirect=redirect) + self._pcall(argv, cwd=cwd, action=action, redirect=redirect, ignore_ret=ignore_ret) except tox.exception.InvocationError: val = sys.exc_info()[1] self.session.report.error(str(val)) @@ -357,7 +368,7 @@ raise def _pcall(self, args, venv=True, cwd=None, extraenv={}, - action=None, redirect=True): + action=None, redirect=True, ignore_ret=False): for name in ("VIRTUALENV_PYTHON", "PYTHONDONTWRITEBYTECODE"): try: del os.environ[name] @@ -369,7 +380,7 @@ try: args[0] = self.getcommandpath(args[0], venv, cwd) env = self._getenv(extraenv) - return action.popen(args, cwd=cwd, env=env, redirect=redirect) + return action.popen(args, cwd=cwd, env=env, redirect=redirect, ignore_ret=ignore_ret) finally: os.environ['PATH'] = old Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 21 20:19:34 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 19:19:34 -0000 Subject: [Pytest-commit] commit/tox: hpk42: Merged in suor/tox/lessen-factor-use-check (pull request #130) Message-ID: <20150221191934.29903.65651@app12.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/0ebe9e55e8c2/ Changeset: 0ebe9e55e8c2 User: hpk42 Date: 2015-02-21 19:19:31+00:00 Summary: Merged in suor/tox/lessen-factor-use-check (pull request #130) Lessen factor use check Affected #: 2 files diff -r 4298877e42165fcc80bccd1cc809583f8178c301 -r 0ebe9e55e8c2e010ddc7e4b10603e3ee0db56a9f tests/test_config.py --- a/tests/test_config.py +++ b/tests/test_config.py @@ -960,6 +960,18 @@ assert configs["py27"].setenv["X"] == "1" assert "X" not in configs["py26"].setenv + @pytest.mark.issue191 + def test_factor_use_not_checked(self, newconfig): + inisource=""" + [tox] + envlist = py27-{a,b} + + [testenv] + deps = b: test + """ + configs = newconfig([], inisource).envconfigs + assert set(configs.keys()) == set(['py27-a', 'py27-b']) + def test_period_in_factor(self, newconfig): inisource=""" [tox] diff -r 4298877e42165fcc80bccd1cc809583f8178c301 -r 0ebe9e55e8c2e010ddc7e4b10603e3ee0db56a9f tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -287,10 +287,18 @@ config.envlist, all_envs = self._getenvdata(reader, toxsection) - # configure testenvs + # factors used in config or predefined known_factors = self._list_section_factors("testenv") known_factors.update(default_factors) known_factors.add("python") + + # factors stated in config envlist + stated_envlist = reader.getdefault(toxsection, "envlist", replace=False) + if stated_envlist: + for env in _split_env(stated_envlist): + known_factors.update(env.split('-')) + + # configure testenvs for name in all_envs: section = testenvprefix + name factors = set(name.split('-')) Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 21 20:19:34 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 19:19:34 -0000 Subject: [Pytest-commit] commit/tox: 2 new changesets Message-ID: <20150221191934.27555.4255@app02.ash-private.bitbucket.org> 2 new commits in tox: https://bitbucket.org/hpk42/tox/commits/81587bb49a77/ Changeset: 81587bb49a77 Branch: lessen-factor-use-check User: suor Date: 2014-12-29 12:09:15+00:00 Summary: Lessen factor use check Fixes issue 191 Affected #: 2 files diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 81587bb49a7706a661fa925dea0eae192118238b tests/test_config.py --- a/tests/test_config.py +++ b/tests/test_config.py @@ -960,6 +960,18 @@ assert configs["py27"].setenv["X"] == "1" assert "X" not in configs["py26"].setenv + @pytest.mark.issue191 + def test_factor_use_not_checked(self, newconfig): + inisource=""" + [tox] + envlist = py27-{a,b} + + [testenv] + deps = b: test + """ + configs = newconfig([], inisource).envconfigs + assert set(configs.keys()) == set(['py27-a', 'py27-b']) + def test_period_in_factor(self, newconfig): inisource=""" [tox] diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 81587bb49a7706a661fa925dea0eae192118238b tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -287,10 +287,18 @@ config.envlist, all_envs = self._getenvdata(reader, toxsection) - # configure testenvs + # factors used in config or predefined known_factors = self._list_section_factors("testenv") known_factors.update(default_factors) known_factors.add("python") + + # factors stated in config envlist + stated_envlist = reader.getdefault(toxsection, "envlist", replace=False) + if stated_envlist: + for env in _split_env(stated_envlist): + known_factors.update(env.split('-')) + + # configure testenvs for name in all_envs: section = testenvprefix + name factors = set(name.split('-')) https://bitbucket.org/hpk42/tox/commits/0ebe9e55e8c2/ Changeset: 0ebe9e55e8c2 User: hpk42 Date: 2015-02-21 19:19:31+00:00 Summary: Merged in suor/tox/lessen-factor-use-check (pull request #130) Lessen factor use check Affected #: 2 files diff -r 4298877e42165fcc80bccd1cc809583f8178c301 -r 0ebe9e55e8c2e010ddc7e4b10603e3ee0db56a9f tests/test_config.py --- a/tests/test_config.py +++ b/tests/test_config.py @@ -960,6 +960,18 @@ assert configs["py27"].setenv["X"] == "1" assert "X" not in configs["py26"].setenv + @pytest.mark.issue191 + def test_factor_use_not_checked(self, newconfig): + inisource=""" + [tox] + envlist = py27-{a,b} + + [testenv] + deps = b: test + """ + configs = newconfig([], inisource).envconfigs + assert set(configs.keys()) == set(['py27-a', 'py27-b']) + def test_period_in_factor(self, newconfig): inisource=""" [tox] diff -r 4298877e42165fcc80bccd1cc809583f8178c301 -r 0ebe9e55e8c2e010ddc7e4b10603e3ee0db56a9f tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -287,10 +287,18 @@ config.envlist, all_envs = self._getenvdata(reader, toxsection) - # configure testenvs + # factors used in config or predefined known_factors = self._list_section_factors("testenv") known_factors.update(default_factors) known_factors.add("python") + + # factors stated in config envlist + stated_envlist = reader.getdefault(toxsection, "envlist", replace=False) + if stated_envlist: + for env in _split_env(stated_envlist): + known_factors.update(env.split('-')) + + # configure testenvs for name in all_envs: section = testenvprefix + name factors = set(name.split('-')) Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 21 21:08:28 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 20:08:28 -0000 Subject: [Pytest-commit] commit/tox: 4 new changesets Message-ID: <20150221200828.31864.99724@app02.ash-private.bitbucket.org> 4 new commits in tox: https://bitbucket.org/hpk42/tox/commits/917f3555fde5/ Changeset: 917f3555fde5 Branch: issue198 User: suor Date: 2014-12-29 10:35:31+00:00 Summary: Fix issue 198: resolve touching factor groups Affected #: 2 files diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 917f3555fde5596a0c1fe96d3d6d110d63e99aca tests/test_config.py --- a/tests/test_config.py +++ b/tests/test_config.py @@ -960,6 +960,19 @@ assert configs["py27"].setenv["X"] == "1" assert "X" not in configs["py26"].setenv + @pytest.mark.issue198 + def test_factors_groups_touch(self, newconfig): + inisource=""" + [tox] + envlist = {a,b}{-x,} + + [testenv] + deps= + a,b,x,y: dep + """ + configs = newconfig([], inisource).envconfigs + assert set(configs.keys()) == set(['a', 'a-x', 'b', 'b-x']) + def test_period_in_factor(self, newconfig): inisource=""" [tox] diff -r 50f3b98fc65b951ab07e6b5e3fbd5a2fc9c48f2c -r 917f3555fde5596a0c1fe96d3d6d110d63e99aca tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -456,7 +456,7 @@ def _expand_envstr(envstr): # split by commas not in groups - tokens = re.split(r'(\{[^}]+\})|,', envstr) + tokens = re.split(r'((?:\{[^}]+\})+)|,', envstr) envlist = [''.join(g).strip() for k, g in itertools.groupby(tokens, key=bool) if k] https://bitbucket.org/hpk42/tox/commits/34c4a7c2845b/ Changeset: 34c4a7c2845b User: hpk42 Date: 2015-02-21 19:33:15+00:00 Summary: Merged in suor/tox/issue198 (pull request #129) Affected #: 3 files diff -r 0ebe9e55e8c2e010ddc7e4b10603e3ee0db56a9f -r 34c4a7c2845b87743b56de3dff123fffd6c0d766 tests/test_config.py --- a/tests/test_config.py +++ b/tests/test_config.py @@ -972,6 +972,19 @@ configs = newconfig([], inisource).envconfigs assert set(configs.keys()) == set(['py27-a', 'py27-b']) + @pytest.mark.issue198 + def test_factors_groups_touch(self, newconfig): + inisource=""" + [tox] + envlist = {a,b}{-x,} + + [testenv] + deps= + a,b,x,y: dep + """ + configs = newconfig([], inisource).envconfigs + assert set(configs.keys()) == set(['a', 'a-x', 'b', 'b-x']) + def test_period_in_factor(self, newconfig): inisource=""" [tox] diff -r 0ebe9e55e8c2e010ddc7e4b10603e3ee0db56a9f -r 34c4a7c2845b87743b56de3dff123fffd6c0d766 tests/test_quickstart.py --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -37,6 +37,7 @@ 'Y', # py32 'Y', # py33 'Y', # py34 + 'Y', # py35 'Y', # pypy 'N', # jython 'py.test', # command to run tests @@ -54,7 +55,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy +envlist = py26, py27, py32, py33, py34, py35, pypy [testenv] commands = py.test @@ -77,6 +78,7 @@ 'Y', # py32 'Y', # py33 'Y', # py34 + 'Y', # py35 'Y', # pypy 'N', # jython 'nosetests', # command to run tests @@ -94,7 +96,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy +envlist = py26, py27, py32, py33, py34, py35, pypy [testenv] commands = nosetests @@ -117,6 +119,7 @@ 'Y', # py32 'Y', # py33 'Y', # py34 + 'Y', # py35 'Y', # pypy 'N', # jython 'trial', # command to run tests @@ -134,7 +137,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy +envlist = py26, py27, py32, py33, py34, py35, pypy [testenv] commands = trial @@ -157,6 +160,7 @@ 'Y', # py32 'Y', # py33 'Y', # py34 + 'Y', # py35 'Y', # pypy 'N', # jython 'py.test', # command to run tests @@ -173,7 +177,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy +envlist = py26, py27, py32, py33, py34, py35, pypy [testenv] commands = py.test @@ -272,7 +276,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy, jython +envlist = py26, py27, py32, py33, py34, py35, pypy, jython [testenv] commands = py.test @@ -295,6 +299,7 @@ '', # py32 '', # py33 '', # py34 + '', # py35 '', # pypy '', # jython '', # command to run tests @@ -312,7 +317,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy, jython +envlist = py26, py27, py32, py33, py34, py35, pypy, jython [testenv] commands = {envpython} setup.py test @@ -339,6 +344,7 @@ '', # py32 '', # py33 '', # py34 + '', # py35 '', # pypy '', # jython '', # command to run tests @@ -357,7 +363,7 @@ # and then run "tox" from this directory. [tox] -envlist = py26, py27, py32, py33, py34, pypy, jython +envlist = py26, py27, py32, py33, py34, py35, pypy, jython [testenv] commands = {envpython} setup.py test @@ -459,6 +465,7 @@ 'py32': True, 'py33': True, 'py34': True, + 'py35': True, 'pypy': True, 'commands': 'nosetests -v', 'deps': 'nose', @@ -470,7 +477,7 @@ # and then run "tox" from this directory. [tox] -envlist = py27, py32, py33, py34, pypy +envlist = py27, py32, py33, py34, py35, pypy [testenv] commands = nosetests -v diff -r 0ebe9e55e8c2e010ddc7e4b10603e3ee0db56a9f -r 34c4a7c2845b87743b56de3dff123fffd6c0d766 tox/_config.py --- a/tox/_config.py +++ b/tox/_config.py @@ -466,7 +466,7 @@ def _expand_envstr(envstr): # split by commas not in groups - tokens = re.split(r'(\{[^}]+\})|,', envstr) + tokens = re.split(r'((?:\{[^}]+\})+)|,', envstr) envlist = [''.join(g).strip() for k, g in itertools.groupby(tokens, key=bool) if k] https://bitbucket.org/hpk42/tox/commits/c728fb2074b3/ Changeset: c728fb2074b3 User: hpk42 Date: 2015-02-21 19:35:40+00:00 Summary: add changelog: fix issue198: fix broken envlist settings, e.g. {py26,py27}{-lint,} Affected #: 1 file diff -r 34c4a7c2845b87743b56de3dff123fffd6c0d766 -r c728fb2074b35cf2a5d2180b461c977447b09a1a CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,9 @@ - fix issue124: ignore command exit codes; when a command has a "-" prefix, tox will ignore the exit code of that command +- fix issue198: fix broken envlist settings, e.g. {py26,py27}{-lint,} + + 1.8.1 ----------- https://bitbucket.org/hpk42/tox/commits/0a85dfb46090/ Changeset: 0a85dfb46090 User: hpk42 Date: 2015-02-21 19:36:45+00:00 Summary: add changelog: fix issue191: lessen factor-use checks Affected #: 1 file diff -r c728fb2074b35cf2a5d2180b461c977447b09a1a -r 0a85dfb460906c3434651b594b591d0426530744 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,8 @@ - fix issue198: fix broken envlist settings, e.g. {py26,py27}{-lint,} +- fix issue191: lessen factor-use checks + 1.8.1 ----------- Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 21 21:08:47 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 21 Feb 2015 20:08:47 -0000 Subject: [Pytest-commit] commit/tox: hpk42: close branch Message-ID: <20150221200847.6103.31823@app04.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/189c82130731/ Changeset: 189c82130731 Branch: issue191 User: hpk42 Date: 2015-02-21 20:08:40+00:00 Summary: close branch Affected #: 0 files Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From issues-reply at bitbucket.org Sun Feb 22 10:43:06 2015 From: issues-reply at bitbucket.org (Terry Chia) Date: Sun, 22 Feb 2015 09:43:06 -0000 Subject: [Pytest-commit] Issue #220: tox does not respect "ignore" configuration. (hpk42/tox) Message-ID: <20150222094306.7873.18293@app06.ash-private.bitbucket.org> New issue 220: tox does not respect "ignore" configuration. https://bitbucket.org/hpk42/tox/issue/220/tox-does-not-respect-ignore-configuration Terry Chia: As [documented](http://flake8.readthedocs.org/en/latest/config.html), tox should respect the "ignore" field in a `tox.ini` config file. tox 1.8.1 does not seem to do that. Here is a minimal reproduction of the bug: https://github.com/Ayrx/tox-bug-repro. I would expect that tox passes without flagging the unused import here. However, I get the following results. ``` $ tox -e pep8 pep8 runtests: PYTHONHASHSEED='2632284098' pep8 runtests: commands[0] | flake8 . ./test.py:1:1: F401 'sys' imported but unused ERROR: InvocationError: '/home/ayrx/code/tox-bug-repro/.tox/pep8/bin/flake8 .' ___________________________________ summary ____________________________________ ERROR: pep8: commands failed $ flake8 . ./test.py:1:1: F401 'sys' imported but unused ``` Here are the packages installed in my virtualenv. ``` $ pip list flake8 (2.3.0) mccabe (0.3) pep8 (1.6.2) pip (6.0.8) py (1.4.26) pyflakes (0.8.1) setuptools (12.2) tox (1.8.1) virtualenv (12.0.7) ``` Let me know if more information is needed. From commits-noreply at bitbucket.org Sun Feb 22 12:37:54 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 11:37:54 -0000 Subject: [Pytest-commit] commit/pytest: 9 new changesets Message-ID: <20150222113754.22639.38708@app07.ash-private.bitbucket.org> 9 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/74af5f248bf4/ Changeset: 74af5f248bf4 Branch: env-addopts User: RonnyPfannschmidt Date: 2015-02-22 10:26:48+00:00 Summary: Close env-addopts branch Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/93297892f253/ Changeset: 93297892f253 Branch: adopt-pytest-docs User: RonnyPfannschmidt Date: 2015-02-22 10:27:25+00:00 Summary: Close adopt-pytest-docs branch Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/0c03b0d86889/ Changeset: 0c03b0d86889 Branch: pastebin-xdist User: RonnyPfannschmidt Date: 2015-02-22 10:28:11+00:00 Summary: Close pastebin-xdist branch Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/c14aca1c0610/ Changeset: c14aca1c0610 Branch: techtonik/readmerst-fix-link-to-pypi-1416719991514 User: RonnyPfannschmidt Date: 2015-02-22 10:28:30+00:00 Summary: Close techtonik/readmerst-fix-link-to-pypi-1416719991514 branch Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/1e690a1455d1/ Changeset: 1e690a1455d1 Branch: okin/only-one-import-on-one-line-if-this-shou-1421239108222 User: RonnyPfannschmidt Date: 2015-02-22 10:29:32+00:00 Summary: Close okin/only-one-import-on-one-line-if-this-shou-1421239108222 branch Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/d31d7f842a7f/ Changeset: d31d7f842a7f Branch: fix-pastebin User: RonnyPfannschmidt Date: 2015-02-22 10:31:05+00:00 Summary: Close fix-pastebin branch Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/cf22549f75a0/ Changeset: cf22549f75a0 Branch: alex_gaynor/mark-pytest-as-a-universal-wheel-1414169551518 User: RonnyPfannschmidt Date: 2015-02-22 10:32:45+00:00 Summary: Close alex_gaynor/mark-pytest-as-a-universal-wheel-1414169551518 branch Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/ec62675c24c2/ Changeset: ec62675c24c2 User: RonnyPfannschmidt Date: 2015-02-22 10:45:07+00:00 Summary: merge in the 2.6 maintenance branch Affected #: 23 files diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf .hgtags --- a/.hgtags +++ b/.hgtags @@ -72,3 +72,4 @@ a4f9639702baa3eb4f3b16e162f74f7b69f3f9e1 2.6.1 a4f25c5e649892b5cc746d21be971e4773478af9 2.6.2 2967aa416a4f3cdb65fc75073a2a148e1f372742 2.6.3 +f03b6de8325f5b6c35cea7c3de092f134ea8ef07 2.6.4 diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -57,6 +57,12 @@ - fix issue614: fixed pastebin support. + +- fix issue620: add explanation in the --genscript target about what + the binary blob means. Thanks Dinu Gherman. + +- fix issue614: fixed pastebin support. + 2.6.3 ----------- diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/assert.txt --- a/doc/en/assert.txt +++ b/doc/en/assert.txt @@ -26,7 +26,7 @@ $ py.test test_assert1.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_assert1.py F @@ -135,7 +135,7 @@ $ py.test test_assert2.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_assert2.py F @@ -152,6 +152,7 @@ E '1' E Extra items in the right set: E '5' + E Use -v to get the full diff test_assert2.py:5: AssertionError ========================= 1 failed in 0.01 seconds ========================= diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/capture.txt --- a/doc/en/capture.txt +++ b/doc/en/capture.txt @@ -64,7 +64,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py .F @@ -78,7 +78,7 @@ test_module.py:9: AssertionError -------------------------- Captured stdout setup --------------------------- - setting up + setting up ==================== 1 failed, 1 passed in 0.01 seconds ==================== Accessing captured output from a test function diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/conf.py --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -18,7 +18,7 @@ # The full version, including alpha/beta/rc tags. # The short X.Y version. version = "2.6" -release = "2.6.3" +release = "2.6.4" import sys, os diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/doctest.txt --- a/doc/en/doctest.txt +++ b/doc/en/doctest.txt @@ -44,12 +44,12 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items mymodule.py . - ========================= 1 passed in 0.05 seconds ========================= + ========================= 1 passed in 0.06 seconds ========================= It is possible to use fixtures using the ``getfixture`` helper:: diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/example/markers.txt --- a/doc/en/example/markers.txt +++ b/doc/en/example/markers.txt @@ -31,7 +31,7 @@ $ py.test -v -m webtest =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_send_http PASSED @@ -43,7 +43,7 @@ $ py.test -v -m "not webtest" =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_something_quick PASSED @@ -62,7 +62,7 @@ $ py.test -v test_server.py::TestClass::test_method =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 5 items test_server.py::TestClass::test_method PASSED @@ -73,7 +73,7 @@ $ py.test -v test_server.py::TestClass =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::TestClass::test_method PASSED @@ -84,7 +84,7 @@ $ py.test -v test_server.py::TestClass test_server.py::test_send_http =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 8 items test_server.py::TestClass::test_method PASSED @@ -120,7 +120,7 @@ $ py.test -v -k http # running with the above defined example module =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_send_http PASSED @@ -132,7 +132,7 @@ $ py.test -k "not send_http" -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_something_quick PASSED @@ -140,13 +140,13 @@ test_server.py::TestClass::test_method PASSED ================= 1 tests deselected by '-knot send_http' ================== - ================== 3 passed, 1 deselected in 0.02 seconds ================== + ================== 3 passed, 1 deselected in 0.01 seconds ================== Or to select "http" and "quick" tests:: $ py.test -k "http or quick" -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_send_http PASSED @@ -334,7 +334,7 @@ $ py.test -E stage2 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_someenv.py s @@ -345,7 +345,7 @@ $ py.test -E stage1 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_someenv.py . @@ -463,12 +463,12 @@ $ py.test -rs # this option reports skip reasons =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_plat.py sss. ========================= short test summary info ========================== - SKIP [3] /tmp/doc-exec-224/conftest.py:12: cannot run on platform linux + SKIP [3] /tmp/doc-exec-68/conftest.py:12: cannot run on platform linux =================== 1 passed, 3 skipped in 0.01 seconds ==================== @@ -476,7 +476,7 @@ $ py.test -m linux2 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_plat.py s @@ -527,7 +527,7 @@ $ py.test -m interface --tb=short =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_module.py FF @@ -548,7 +548,7 @@ $ py.test -m "interface or event" --tb=short =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_module.py FFF diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/example/nonpython.txt --- a/doc/en/example/nonpython.txt +++ b/doc/en/example/nonpython.txt @@ -27,10 +27,10 @@ nonpython $ py.test test_simple.yml =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items - test_simple.yml .F + test_simple.yml F. ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ @@ -56,11 +56,11 @@ nonpython $ py.test -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 2 items + test_simple.yml::usecase: hello FAILED test_simple.yml::usecase: ok PASSED - test_simple.yml::usecase: hello FAILED ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ @@ -74,10 +74,10 @@ nonpython $ py.test --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items + - ============================= in 0.03 seconds ============================= diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/example/parametrize.txt --- a/doc/en/example/parametrize.txt +++ b/doc/en/example/parametrize.txt @@ -181,7 +181,7 @@ $ py.test test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_scenarios.py .... @@ -193,7 +193,7 @@ $ py.test --collect-only test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items @@ -257,7 +257,7 @@ $ py.test test_backends.py --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items @@ -272,7 +272,7 @@ ================================= FAILURES ================================= _________________________ test_db_initialized[d2] __________________________ - db = + db = def test_db_initialized(db): # a dummy test @@ -281,7 +281,7 @@ E Failed: deliberately failing for demo purposes test_backends.py:6: Failed - 1 failed, 1 passed in 0.02 seconds + 1 failed, 1 passed in 0.01 seconds The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``db`` fixture function has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase. @@ -326,16 +326,16 @@ $ py.test -q F.. ================================= FAILURES ================================= - ________________________ TestClass.test_equals[1-2] ________________________ + ________________________ TestClass.test_equals[2-1] ________________________ - self = , a = 1, b = 2 + self = , a = 1, b = 2 def test_equals(self, a, b): > assert a == b E assert 1 == 2 test_parametrize.py:18: AssertionError - 1 failed, 2 passed in 0.02 seconds + 1 failed, 2 passed in 0.01 seconds Indirect parametrization with multiple fixtures -------------------------------------------------------------- @@ -358,8 +358,8 @@ ================================= FAILURES ================================= ________________ test_basic_objects[python3.4-python2.6-42] ________________ - python1 = - python2 = , obj = 42 + python1 = + python2 = , obj = 42 @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -372,7 +372,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py' + cmd = '/home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p0/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -397,9 +397,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p0/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p0/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p0/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.6/pickle.py", line 1370, in load E return Unpickler(file).load() @@ -411,11 +411,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p0/load.py _______________ test_basic_objects[python3.4-python2.6-obj1] _______________ - python1 = - python2 = , obj = {} + python1 = + python2 = , obj = {} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -428,7 +428,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py' + cmd = '/home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p1/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -453,9 +453,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p1/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p1/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p1/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.6/pickle.py", line 1370, in load E return Unpickler(file).load() @@ -467,11 +467,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p1/load.py _______________ test_basic_objects[python3.4-python2.6-obj2] _______________ - python1 = - python2 = , obj = {1: 3} + python1 = + python2 = , obj = {1: 3} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -484,7 +484,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py' + cmd = '/home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p2/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -509,9 +509,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p2/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p2/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p2/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.6/pickle.py", line 1370, in load E return Unpickler(file).load() @@ -523,11 +523,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p2/load.py ________________ test_basic_objects[python3.4-python2.7-42] ________________ - python1 = - python2 = , obj = 42 + python1 = + python2 = , obj = 42 @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -540,7 +540,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py' + cmd = '/home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p3/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -565,9 +565,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p3/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p3/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p3/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.7/pickle.py", line 1378, in load E return Unpickler(file).load() @@ -579,11 +579,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p3/load.py _______________ test_basic_objects[python3.4-python2.7-obj1] _______________ - python1 = - python2 = , obj = {} + python1 = + python2 = , obj = {} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -596,7 +596,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py' + cmd = '/home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p4/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -621,9 +621,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p4/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p4/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p4/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.7/pickle.py", line 1378, in load E return Unpickler(file).load() @@ -635,11 +635,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p4/load.py _______________ test_basic_objects[python3.4-python2.7-obj2] _______________ - python1 = - python2 = , obj = {1: 3} + python1 = + python2 = , obj = {1: 3} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -652,7 +652,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py' + cmd = '/home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p5/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -677,9 +677,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p5/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p5/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p5/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.7/pickle.py", line 1378, in load E return Unpickler(file).load() @@ -691,8 +691,8 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py - 6 failed, 21 passed in 1.36 seconds + /tmp/pytest-111/test_basic_objects_python3_4_p5/load.py + 6 failed, 21 passed in 1.66 seconds Indirect parametrization of optional implementations/imports -------------------------------------------------------------------- @@ -739,12 +739,12 @@ $ py.test -rs test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py .s ========================= short test summary info ========================== - SKIP [1] /tmp/doc-exec-226/conftest.py:10: could not import 'opt2' + SKIP [1] /tmp/doc-exec-70/conftest.py:10: could not import 'opt2' =================== 1 passed, 1 skipped in 0.01 seconds ==================== diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/example/pythoncollection.txt --- a/doc/en/example/pythoncollection.txt +++ b/doc/en/example/pythoncollection.txt @@ -43,7 +43,7 @@ $ py.test --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items @@ -88,7 +88,7 @@ . $ py.test --collect-only pythoncollection.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items @@ -141,10 +141,10 @@ $ py.test --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 0 items - ============================= in 0.01 seconds ============================= + ============================= in 0.00 seconds ============================= If you run with a Python3 interpreter the moduled added through the conftest.py file will not be considered for test collection. diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/example/reportingdemo.txt --- a/doc/en/example/reportingdemo.txt +++ b/doc/en/example/reportingdemo.txt @@ -13,7 +13,7 @@ assertion $ py.test failure_demo.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 42 items failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF @@ -30,7 +30,7 @@ failure_demo.py:15: AssertionError _________________________ TestFailing.test_simple __________________________ - self = + self = def test_simple(self): def f(): @@ -40,13 +40,13 @@ > assert f() == g() E assert 42 == 43 - E + where 42 = .f at 0x2adb9887e6a8>() - E + and 43 = .g at 0x2adb9887e598>() + E + where 42 = .f at 0x2b4436f1e6a8>() + E + and 43 = .g at 0x2b4436f1e7b8>() failure_demo.py:28: AssertionError ____________________ TestFailing.test_simple_multiline _____________________ - self = + self = def test_simple_multiline(self): otherfunc_multi( @@ -66,19 +66,19 @@ failure_demo.py:11: AssertionError ___________________________ TestFailing.test_not ___________________________ - self = + self = def test_not(self): def f(): return 42 > assert not f() E assert not 42 - E + where 42 = .f at 0x2adb9887e840>() + E + where 42 = .f at 0x2b4436f1ebf8>() failure_demo.py:38: AssertionError _________________ TestSpecialisedExplanations.test_eq_text _________________ - self = + self = def test_eq_text(self): > assert 'spam' == 'eggs' @@ -89,7 +89,7 @@ failure_demo.py:42: AssertionError _____________ TestSpecialisedExplanations.test_eq_similar_text _____________ - self = + self = def test_eq_similar_text(self): > assert 'foo 1 bar' == 'foo 2 bar' @@ -102,7 +102,7 @@ failure_demo.py:45: AssertionError ____________ TestSpecialisedExplanations.test_eq_multiline_text ____________ - self = + self = def test_eq_multiline_text(self): > assert 'foo\nspam\nbar' == 'foo\neggs\nbar' @@ -115,7 +115,7 @@ failure_demo.py:48: AssertionError ______________ TestSpecialisedExplanations.test_eq_long_text _______________ - self = + self = def test_eq_long_text(self): a = '1'*100 + 'a' + '2'*100 @@ -132,7 +132,7 @@ failure_demo.py:53: AssertionError _________ TestSpecialisedExplanations.test_eq_long_text_multiline __________ - self = + self = def test_eq_long_text_multiline(self): a = '1\n'*100 + 'a' + '2\n'*100 @@ -156,17 +156,18 @@ failure_demo.py:58: AssertionError _________________ TestSpecialisedExplanations.test_eq_list _________________ - self = + self = def test_eq_list(self): > assert [0, 1, 2] == [0, 1, 3] E assert [0, 1, 2] == [0, 1, 3] E At index 2 diff: 2 != 3 + E Use -v to get the full diff failure_demo.py:61: AssertionError ______________ TestSpecialisedExplanations.test_eq_list_long _______________ - self = + self = def test_eq_list_long(self): a = [0]*100 + [1] + [3]*100 @@ -174,11 +175,12 @@ > assert a == b E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...] E At index 100 diff: 1 != 2 + E Use -v to get the full diff failure_demo.py:66: AssertionError _________________ TestSpecialisedExplanations.test_eq_dict _________________ - self = + self = def test_eq_dict(self): > assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0} @@ -190,11 +192,12 @@ E {'c': 0} E Right contains more items: E {'d': 0} + E Use -v to get the full diff failure_demo.py:69: AssertionError _________________ TestSpecialisedExplanations.test_eq_set __________________ - self = + self = def test_eq_set(self): > assert set([0, 10, 11, 12]) == set([0, 20, 21]) @@ -206,21 +209,23 @@ E Extra items in the right set: E 20 E 21 + E Use -v to get the full diff failure_demo.py:72: AssertionError _____________ TestSpecialisedExplanations.test_eq_longer_list ______________ - self = + self = def test_eq_longer_list(self): > assert [1,2] == [1,2,3] E assert [1, 2] == [1, 2, 3] E Right contains more items, first extra item: 3 + E Use -v to get the full diff failure_demo.py:75: AssertionError _________________ TestSpecialisedExplanations.test_in_list _________________ - self = + self = def test_in_list(self): > assert 1 in [0, 2, 3, 4, 5] @@ -229,7 +234,7 @@ failure_demo.py:78: AssertionError __________ TestSpecialisedExplanations.test_not_in_text_multiline __________ - self = + self = def test_not_in_text_multiline(self): text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail' @@ -247,7 +252,7 @@ failure_demo.py:82: AssertionError ___________ TestSpecialisedExplanations.test_not_in_text_single ____________ - self = + self = def test_not_in_text_single(self): text = 'single foo line' @@ -260,7 +265,7 @@ failure_demo.py:86: AssertionError _________ TestSpecialisedExplanations.test_not_in_text_single_long _________ - self = + self = def test_not_in_text_single_long(self): text = 'head ' * 50 + 'foo ' + 'tail ' * 20 @@ -273,7 +278,7 @@ failure_demo.py:90: AssertionError ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______ - self = + self = def test_not_in_text_single_long_term(self): text = 'head ' * 50 + 'f'*70 + 'tail ' * 20 @@ -292,7 +297,7 @@ i = Foo() > assert i.b == 2 E assert 1 == 2 - E + where 1 = .Foo object at 0x2adb987b5470>.b + E + where 1 = .Foo object at 0x2b4436e42ac8>.b failure_demo.py:101: AssertionError _________________________ test_attribute_instance __________________________ @@ -302,8 +307,8 @@ b = 1 > assert Foo().b == 2 E assert 1 == 2 - E + where 1 = .Foo object at 0x2adb987d0390>.b - E + where .Foo object at 0x2adb987d0390> = .Foo'>() + E + where 1 = .Foo object at 0x2b4436f185c0>.b + E + where .Foo object at 0x2b4436f185c0> = .Foo'>() failure_demo.py:107: AssertionError __________________________ test_attribute_failure __________________________ @@ -319,7 +324,7 @@ failure_demo.py:116: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - self = .Foo object at 0x2adb98822cf8> + self = .Foo object at 0x2b4436f16a58> def _get_b(self): > raise Exception('Failed to get attrib') @@ -335,15 +340,15 @@ b = 2 > assert Foo().b == Bar().b E assert 1 == 2 - E + where 1 = .Foo object at 0x2adb98841dd8>.b - E + where .Foo object at 0x2adb98841dd8> = .Foo'>() - E + and 2 = .Bar object at 0x2adb98841a90>.b - E + where .Bar object at 0x2adb98841a90> = .Bar'>() + E + where 1 = .Foo object at 0x2b4436f12a90>.b + E + where .Foo object at 0x2b4436f12a90> = .Foo'>() + E + and 2 = .Bar object at 0x2b4436f12ac8>.b + E + where .Bar object at 0x2b4436f12ac8> = .Bar'>() failure_demo.py:124: AssertionError __________________________ TestRaises.test_raises __________________________ - self = + self = def test_raises(self): s = 'qwe' @@ -358,7 +363,7 @@ <0-codegen /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1028>:1: ValueError ______________________ TestRaises.test_raises_doesnt _______________________ - self = + self = def test_raises_doesnt(self): > raises(IOError, "int('3')") @@ -367,7 +372,7 @@ failure_demo.py:136: Failed __________________________ TestRaises.test_raise ___________________________ - self = + self = def test_raise(self): > raise ValueError("demo error") @@ -376,7 +381,7 @@ failure_demo.py:139: ValueError ________________________ TestRaises.test_tupleerror ________________________ - self = + self = def test_tupleerror(self): > a,b = [1] @@ -385,7 +390,7 @@ failure_demo.py:142: ValueError ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______ - self = + self = def test_reinterpret_fails_with_print_for_the_fun_of_it(self): l = [1,2,3] @@ -398,7 +403,7 @@ l is [1, 2, 3] ________________________ TestRaises.test_some_error ________________________ - self = + self = def test_some_error(self): > if namenotexi: @@ -426,7 +431,7 @@ <2-codegen 'abc-123' /home/hpk/p/pytest/doc/en/example/assertion/failure_demo.py:162>:2: AssertionError ____________________ TestMoreErrors.test_complex_error _____________________ - self = + self = def test_complex_error(self): def f(): @@ -450,7 +455,7 @@ failure_demo.py:5: AssertionError ___________________ TestMoreErrors.test_z1_unpack_error ____________________ - self = + self = def test_z1_unpack_error(self): l = [] @@ -460,7 +465,7 @@ failure_demo.py:179: ValueError ____________________ TestMoreErrors.test_z2_type_error _____________________ - self = + self = def test_z2_type_error(self): l = 3 @@ -470,19 +475,19 @@ failure_demo.py:183: TypeError ______________________ TestMoreErrors.test_startswith ______________________ - self = + self = def test_startswith(self): s = "123" g = "456" > assert s.startswith(g) - E assert ('456') - E + where = '123'.startswith + E assert ('456') + E + where = '123'.startswith failure_demo.py:188: AssertionError __________________ TestMoreErrors.test_startswith_nested ___________________ - self = + self = def test_startswith_nested(self): def f(): @@ -490,15 +495,15 @@ def g(): return "456" > assert f().startswith(g()) - E assert ('456') - E + where = '123'.startswith - E + where '123' = .f at 0x2adb9887e9d8>() - E + and '456' = .g at 0x2adb9887e7b8>() + E assert ('456') + E + where = '123'.startswith + E + where '123' = .f at 0x2b4436f1e950>() + E + and '456' = .g at 0x2b4436f1e840>() failure_demo.py:195: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -508,18 +513,18 @@ failure_demo.py:198: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = + self = def test_instance(self): self.x = 6*7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = .x + E + where 42 = .x failure_demo.py:202: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -529,7 +534,7 @@ failure_demo.py:205: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -540,7 +545,7 @@ failure_demo.py:210: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -554,7 +559,7 @@ failure_demo.py:221: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -571,7 +576,7 @@ failure_demo.py:227: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: @@ -589,4 +594,4 @@ E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a failure_demo.py:237: AssertionError - ======================== 42 failed in 0.29 seconds ========================= + ======================== 42 failed in 0.23 seconds ========================= diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/example/simple.txt --- a/doc/en/example/simple.txt +++ b/doc/en/example/simple.txt @@ -55,7 +55,7 @@ test_sample.py:6: AssertionError --------------------------- Captured stdout call --------------------------- first - 1 failed in 0.02 seconds + 1 failed in 0.01 seconds And now with supplying a command line option:: @@ -108,9 +108,9 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 0 items - + ============================= in 0.00 seconds ============================= .. _`excontrolskip`: @@ -152,12 +152,12 @@ $ py.test -rs # "-rs" means report details on the little 's' =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py .s ========================= short test summary info ========================== - SKIP [1] /tmp/doc-exec-229/conftest.py:9: need --runslow option to run + SKIP [1] /tmp/doc-exec-73/conftest.py:9: need --runslow option to run =================== 1 passed, 1 skipped in 0.01 seconds ==================== @@ -165,11 +165,11 @@ $ py.test --runslow =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items - + test_module.py .. - + ========================= 2 passed in 0.01 seconds ========================= Writing well integrated assertion helpers @@ -256,10 +256,10 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 project deps: mylib-1.1 collected 0 items - + ============================= in 0.00 seconds ============================= .. regendoc:wipe @@ -279,20 +279,20 @@ $ py.test -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 info1: did you know that ... did you? collecting ... collected 0 items - + ============================= in 0.00 seconds ============================= and nothing when run plainly:: $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 0 items - + ============================= in 0.00 seconds ============================= profiling test duration @@ -322,7 +322,7 @@ $ py.test --durations=3 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_some_are_slow.py ... @@ -330,8 +330,8 @@ ========================= slowest 3 test durations ========================= 0.20s call test_some_are_slow.py::test_funcslow2 0.10s call test_some_are_slow.py::test_funcslow1 - 0.00s teardown test_some_are_slow.py::test_funcslow1 - ========================= 3 passed in 0.32 seconds ========================= + 0.00s setup test_some_are_slow.py::test_funcslow2 + ========================= 3 passed in 0.31 seconds ========================= incremental testing - test steps --------------------------------------------------- @@ -383,7 +383,7 @@ $ py.test -rx =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_step.py .Fx. @@ -391,7 +391,7 @@ ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - self = + self = def test_modification(self): > assert 0 @@ -453,7 +453,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 7 items test_step.py .Fx. @@ -463,17 +463,17 @@ ================================== ERRORS ================================== _______________________ ERROR at setup of test_root ________________________ - file /tmp/doc-exec-229/b/test_error.py, line 1 + file /tmp/doc-exec-73/b/test_error.py, line 1 def test_root(db): # no db here, will error out fixture 'db' not found - available fixtures: capsys, pytestconfig, monkeypatch, tmpdir, recwarn, capfd + available fixtures: monkeypatch, pytestconfig, tmpdir, capfd, capsys, recwarn use 'py.test --fixtures [testpath]' for help on them. - /tmp/doc-exec-229/b/test_error.py:1 + /tmp/doc-exec-73/b/test_error.py:1 ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - self = + self = def test_modification(self): > assert 0 @@ -482,25 +482,25 @@ test_step.py:9: AssertionError _________________________________ test_a1 __________________________________ - db = + db = def test_a1(db): > assert 0, db # to show value - E AssertionError: + E AssertionError: E assert 0 a/test_db.py:2: AssertionError _________________________________ test_a2 __________________________________ - db = + db = def test_a2(db): > assert 0, db # to show value - E AssertionError: + E AssertionError: E assert 0 a/test_db2.py:2: AssertionError - ========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.04 seconds ========== + ========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.03 seconds ========== The two test modules in the ``a`` directory see the same ``db`` fixture instance while the one test in the sister-directory ``b`` doesn't see it. We could of course @@ -555,7 +555,7 @@ $ py.test test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py FF @@ -563,7 +563,7 @@ ================================= FAILURES ================================= ________________________________ test_fail1 ________________________________ - tmpdir = local('/tmp/pytest-22/test_fail10') + tmpdir = local('/tmp/pytest-112/test_fail10') def test_fail1(tmpdir): > assert 0 @@ -577,12 +577,12 @@ E assert 0 test_module.py:4: AssertionError - ========================= 2 failed in 0.01 seconds ========================= + ========================= 2 failed in 0.02 seconds ========================= you will have a "failures" file which contains the failing test ids:: $ cat failures - test_module.py::test_fail1 (/tmp/pytest-22/test_fail10) + test_module.py::test_fail1 (/tmp/pytest-112/test_fail10) test_module.py::test_fail2 Making test result information available in fixtures @@ -645,7 +645,7 @@ $ py.test -s test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_module.py Esetting up a test failed! test_module.py::test_setup_fails diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/example/special.txt --- a/doc/en/example/special.txt +++ b/doc/en/example/special.txt @@ -69,4 +69,4 @@ .test other .test_unit1 method called . - 4 passed in 0.05 seconds + 4 passed in 0.04 seconds diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/fixture.txt --- a/doc/en/fixture.txt +++ b/doc/en/fixture.txt @@ -76,7 +76,7 @@ $ py.test test_smtpsimple.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_smtpsimple.py F @@ -84,7 +84,7 @@ ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - smtp = + smtp = def test_ehlo(smtp): response, msg = smtp.ehlo() @@ -93,7 +93,7 @@ E TypeError: Type str doesn't support the buffer API test_smtpsimple.py:11: TypeError - ========================= 1 failed in 0.20 seconds ========================= + ========================= 1 failed in 0.28 seconds ========================= In the failure traceback we see that the test function was called with a ``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture @@ -193,7 +193,7 @@ $ py.test test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py FF @@ -201,7 +201,7 @@ ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - smtp = + smtp = def test_ehlo(smtp): response = smtp.ehlo() @@ -212,7 +212,7 @@ test_module.py:5: TypeError ________________________________ test_noop _________________________________ - smtp = + smtp = def test_noop(smtp): response = smtp.noop() @@ -221,7 +221,7 @@ E assert 0 test_module.py:11: AssertionError - ========================= 2 failed in 0.17 seconds ========================= + ========================= 2 failed in 0.28 seconds ========================= You see the two ``assert 0`` failing and more importantly you can also see that the same (module-scoped) ``smtp`` object was passed into the two @@ -269,7 +269,7 @@ $ py.test -s -q --tb=no FFteardown smtp - 2 failed in 0.16 seconds + 2 failed in 0.21 seconds We see that the ``smtp`` instance is finalized after the two tests finished execution. Note that if we decorated our fixture @@ -310,7 +310,7 @@ $ py.test -s -q --tb=no FF - 2 failed in 0.16 seconds + 2 failed in 0.19 seconds Let's quickly create another test module that actually sets the server URL in its module namespace:: @@ -378,7 +378,7 @@ ================================= FAILURES ================================= __________________________ test_ehlo[merlinux.eu] __________________________ - smtp = + smtp = def test_ehlo(smtp): response = smtp.ehlo() @@ -389,7 +389,7 @@ test_module.py:5: TypeError __________________________ test_noop[merlinux.eu] __________________________ - smtp = + smtp = def test_noop(smtp): response = smtp.noop() @@ -400,7 +400,7 @@ test_module.py:11: AssertionError ________________________ test_ehlo[mail.python.org] ________________________ - smtp = + smtp = def test_ehlo(smtp): response = smtp.ehlo() @@ -410,10 +410,10 @@ test_module.py:5: TypeError -------------------------- Captured stdout setup --------------------------- - finalizing + finalizing ________________________ test_noop[mail.python.org] ________________________ - smtp = + smtp = def test_noop(smtp): response = smtp.noop() @@ -422,7 +422,7 @@ E assert 0 test_module.py:11: AssertionError - 4 failed in 6.02 seconds + 4 failed in 7.02 seconds We see that our two test functions each ran twice, against the different ``smtp`` instances. Note also, that with the ``mail.python.org`` @@ -517,13 +517,13 @@ $ py.test -v test_appsetup.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 2 items test_appsetup.py::test_smtp_exists[merlinux.eu] PASSED test_appsetup.py::test_smtp_exists[mail.python.org] PASSED - ========================= 2 passed in 5.45 seconds ========================= + ========================= 2 passed in 6.63 seconds ========================= Due to the parametrization of ``smtp`` the test will run twice with two different ``App`` instances and respective smtp servers. There is no @@ -581,7 +581,7 @@ $ py.test -v -s test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 8 items test_module.py::test_0[1] test0 1 diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/getting-started.txt --- a/doc/en/getting-started.txt +++ b/doc/en/getting-started.txt @@ -27,7 +27,7 @@ To check your installation has installed the correct version:: $ py.test --version - This is pytest version 2.6.3, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py + This is pytest version 2.6.4, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py If you get an error checkout :ref:`installation issues`. @@ -49,7 +49,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_sample.py F @@ -127,7 +127,7 @@ ================================= FAILURES ================================= ____________________________ TestClass.test_two ____________________________ - self = + self = def test_two(self): x = "hello" @@ -163,7 +163,7 @@ ================================= FAILURES ================================= _____________________________ test_needsfiles ______________________________ - tmpdir = local('/tmp/pytest-18/test_needsfiles0') + tmpdir = local('/tmp/pytest-108/test_needsfiles0') def test_needsfiles(tmpdir): print (tmpdir) @@ -172,8 +172,8 @@ test_tmpdir.py:3: AssertionError --------------------------- Captured stdout call --------------------------- - /tmp/pytest-18/test_needsfiles0 - 1 failed in 0.01 seconds + /tmp/pytest-108/test_needsfiles0 + 1 failed in 0.02 seconds Before the test runs, a unique-per-test-invocation temporary directory was created. More info at :ref:`tmpdir handling`. diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/index.txt --- a/doc/en/index.txt +++ b/doc/en/index.txt @@ -1,14 +1,10 @@ .. _features: -.. note:: - Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? April 2015 is `adopt pytest month`_! .. _`adopt pytest month`: adopt.html - - pytest: helps you write better programs ============================================= diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/parametrize.txt --- a/doc/en/parametrize.txt +++ b/doc/en/parametrize.txt @@ -53,7 +53,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_expectation.py ..F @@ -100,12 +100,12 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_expectation.py ..x - =================== 2 passed, 1 xfailed in 0.02 seconds ==================== + =================== 2 passed, 1 xfailed in 0.01 seconds ==================== The one parameter set which caused a failure previously now shows up as an "xfailed (expected to fail)" test. @@ -170,8 +170,8 @@ def test_valid_string(stringinput): > assert stringinput.isalpha() - E assert () - E + where = '!'.isalpha + E assert () + E + where = '!'.isalpha test_strings.py:3: AssertionError 1 failed in 0.01 seconds @@ -185,7 +185,7 @@ $ py.test -q -rs test_strings.py s ========================= short test summary info ========================== - SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1139: got empty parameter set, function test_valid_string at /tmp/doc-exec-180/test_strings.py:1 + SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1139: got empty parameter set, function test_valid_string at /tmp/doc-exec-23/test_strings.py:1 1 skipped in 0.01 seconds For further examples, you might want to look at :ref:`more diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/skipping.txt --- a/doc/en/skipping.txt +++ b/doc/en/skipping.txt @@ -164,7 +164,7 @@ example $ py.test -rx xfail_demo.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 7 items xfail_demo.py xxxxxxx @@ -182,7 +182,7 @@ reason: reason XFAIL xfail_demo.py::test_hello7 - ======================== 7 xfailed in 0.05 seconds ========================= + ======================== 7 xfailed in 0.04 seconds ========================= .. _`skip/xfail with parametrize`: diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/tmpdir.txt --- a/doc/en/tmpdir.txt +++ b/doc/en/tmpdir.txt @@ -29,7 +29,7 @@ $ py.test test_tmpdir.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_tmpdir.py F @@ -37,7 +37,7 @@ ================================= FAILURES ================================= _____________________________ test_create_file _____________________________ - tmpdir = local('/tmp/pytest-19/test_create_file0') + tmpdir = local('/tmp/pytest-109/test_create_file0') def test_create_file(tmpdir): p = tmpdir.mkdir("sub").join("hello.txt") @@ -48,7 +48,7 @@ E assert 0 test_tmpdir.py:7: AssertionError - ========================= 1 failed in 0.01 seconds ========================= + ========================= 1 failed in 0.02 seconds ========================= .. _`base temporary directory`: diff -r 46d5ac0ba396af887969a3cc9940fccba5ff1955 -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf doc/en/unittest.txt --- a/doc/en/unittest.txt +++ b/doc/en/unittest.txt @@ -88,7 +88,7 @@ $ py.test test_unittest_db.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_unittest_db.py FF @@ -101,7 +101,7 @@ def test_method1(self): assert hasattr(self, "db") > assert 0, self.db # fail for demo purposes - E AssertionError: .DummyDB object at 0x2b938b865208> + E AssertionError: .DummyDB object at 0x2b98cc5a2e80> E assert 0 test_unittest_db.py:9: AssertionError @@ -111,11 +111,11 @@ def test_method2(self): > assert 0, self.db # fail for demo purposes - E AssertionError: .DummyDB object at 0x2b938b865208> + E AssertionError: .DummyDB object at 0x2b98cc5a2e80> E assert 0 test_unittest_db.py:12: AssertionError - ========================= 2 failed in 0.05 seconds ========================= + ========================= 2 failed in 0.04 seconds ========================= This default pytest traceback shows that the two test methods share the same ``self.db`` instance which was our intention https://bitbucket.org/hpk42/pytest/commits/181d08e03c11/ Changeset: 181d08e03c11 User: RonnyPfannschmidt Date: 2015-02-22 11:29:26+00:00 Summary: merge Affected #: 3 files diff -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf -r 181d08e03c11f34aac5f3358a92cc4d1d5557963 doc/en/faq.txt --- a/doc/en/faq.txt +++ b/doc/en/faq.txt @@ -30,15 +30,15 @@ If you are using trial's unittest.TestCase chances are that you can just run your tests even if you return Deferreds. In addition, there also is a dedicated `pytest-twisted -`_ plugin which allows to -return deferreds from pytest-style tests, allowing to use +`_ plugin which allows you to +return deferreds from pytest-style tests, allowing the use of :ref:`fixtures` and other features. how does pytest work with Django? ++++++++++++++++++++++++++++++++++++++++++++++ In 2012, some work is going into the `pytest-django plugin `_. It substitutes the usage of Django's -``manage.py test`` and allows to use all pytest features_ most of which +``manage.py test`` and allows the use of all pytest features_ most of which are not available from Django directly. .. _features: features.html @@ -49,7 +49,7 @@ Around 2007 (version ``0.8``) some people thought that ``pytest`` was using too much "magic". It had been part of the `pylib`_ which -contains a lot of unreleated python library code. Around 2010 there +contains a lot of unrelated python library code. Around 2010 there was a major cleanup refactoring, which removed unused or deprecated code and resulted in the new ``pytest`` PyPI package which strictly contains only test-related code. This release also brought a complete pluginification @@ -63,7 +63,7 @@ Nowadays, ``pytest`` explicitely rewrites assert statements in test modules in order to provide more useful :ref:`assert feedback `. This completely avoids previous issues of confusing assertion-reporting. -It also means, that you can use Python's ``-O`` optimization without loosing +It also means, that you can use Python's ``-O`` optimization without losing assertions in test modules. ``pytest`` contains a second, mostly obsolete, assert debugging technique, @@ -152,13 +152,13 @@ Issues with pytest, multiprocess and setuptools? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -On windows the multiprocess package will instantiate sub processes +On Windows the multiprocess package will instantiate sub processes by pickling and thus implicitly re-import a lot of local modules. Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'`` protect its generated command line script. This leads to infinite recursion when running a test that instantiates Processes. -As of middle 2013, there shouldn't be a problem anymore when you +As of mid-2013, there shouldn't be a problem anymore when you use the standard setuptools (note that distribute has been merged back into setuptools which is now shipped directly with virtualenv). diff -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf -r 181d08e03c11f34aac5f3358a92cc4d1d5557963 testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -3,8 +3,6 @@ import pdb -xfail_if_pdbpp_installed = pytest.mark.xfail(hasattr(pdb, "__author__"), - reason="doctest/pdbpp problem: https://bitbucket.org/antocuni/pdb/issue/24/doctests-fail-when-pdbpp-is-installed", run=False) class TestDoctests: @@ -161,7 +159,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_external_and_issue116(self, testdir): p = testdir.mkpydir("hello") p.join("__init__.py").write(py.code.Source(""" @@ -201,7 +198,6 @@ "*test_txtfile_failing.txt:2: DocTestFailure" ]) - @xfail_if_pdbpp_installed def test_txtfile_with_fixtures(self, testdir): p = testdir.maketxtfile(""" >>> dir = getfixture('tmpdir') @@ -211,7 +207,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_txtfile_with_usefixtures_in_ini(self, testdir): testdir.makeini(""" [pytest] @@ -232,7 +227,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_with_fixtures(self, testdir): p = testdir.makepyfile(""" ''' @@ -244,7 +238,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_three_tests(self, testdir): p = testdir.makepyfile(""" ''' @@ -270,7 +263,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=3) - @xfail_if_pdbpp_installed def test_doctestmodule_two_tests_one_fail(self, testdir): p = testdir.makepyfile(""" class MyClass: diff -r ec62675c24c2454d9f90f5e59a4f3e1e6aff89bf -r 181d08e03c11f34aac5f3358a92cc4d1d5557963 testing/test_pdb.py --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -2,7 +2,6 @@ import py import sys -from test_doctest import xfail_if_pdbpp_installed class TestPDB: def pytest_funcarg__pdblist(self, request): @@ -187,7 +186,6 @@ if child.isalive(): child.wait() - @xfail_if_pdbpp_installed def test_pdb_interaction_doctest(self, testdir): p1 = testdir.makepyfile(""" import pytest Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sun Feb 22 12:51:31 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 11:51:31 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150222115131.19507.28259@app07.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/b63fe8f9c03d/ Changeset: b63fe8f9c03d Branch: remove_pdbpp_xfail User: RonnyPfannschmidt Date: 2015-02-22 11:50:46+00:00 Summary: close remove_pdbpp_xfail Affected #: 0 files https://bitbucket.org/hpk42/pytest/commits/f1ddd1e78f1e/ Changeset: f1ddd1e78f1e Branch: jeffwidman/fix-faq-grammar-and-spelling-1423641159173 User: RonnyPfannschmidt Date: 2015-02-22 11:51:10+00:00 Summary: close jeffwidman/fix-faq-grammar-and-spelling-1423641159173 Affected #: 0 files Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sun Feb 22 12:55:06 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 11:55:06 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: begin with creating a flake8 tox env Message-ID: <20150222115506.11549.28766@app01.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/52f65c68c647/ Changeset: 52f65c68c647 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 11:54:45+00:00 Summary: begin with creating a flake8 tox env Affected #: 1 file diff -r f1ddd1e78f1e8a83376ac7a097cc232a9aae06fb -r 52f65c68c647c2addce892b9c93a45fbfb477e11 tox.ini --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] distshare={homedir}/.tox/distshare -envlist=flakes,py26,py27,py34,pypy,py27-pexpect,py33-pexpect,py27-nobyte,py32,py33,py27-xdist,py33-xdist,py27-trial,py33-trial,doctesting,py27-cxfreeze +envlist=flake8,py26,py27,py34,pypy,py27-pexpect,py33-pexpect,py27-nobyte,py32,py33,py27-xdist,py33-xdist,py27-trial,py33-trial,doctesting,py27-cxfreeze [testenv] changedir=testing @@ -13,10 +13,10 @@ changedir=. commands= py.test --genscript=pytest1 -[testenv:flakes] +[testenv:flake8] changedir= -deps = pytest-flakes>=0.2 -commands = py.test --flakes -m flakes _pytest testing +deps = flake9 +commands = flake8 {posargs:_pytest testing pytest.py setup.py} [testenv:py27-xdist] changedir=. @@ -141,5 +141,7 @@ python_files=test_*.py *_test.py testing/*/*.py python_classes=Test Acceptance python_functions=test -pep8ignore = E401 E225 E261 E128 E124 E302 norecursedirs = .tox ja .hg + +[flake8] +max-complexity = 10 Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 13:01:09 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 12:01:09 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 376 Message-ID: <20150222120103.10178.96057@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/376 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3850:f1ddd1e78f1e Author : Ronny Pfannschmidt Branch : jeffwidman/fix-faq-grammar-and-spelling-1423641159173 Message: close jeffwidman/fix-faq-grammar-and-spelling-1423641159173 -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Sun Feb 22 13:09:21 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 12:09:21 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 377 Message-ID: <20150222120834.109579.1830@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/377 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3851:52f65c68c647 Author : Ronny Pfannschmidt Branch : flake8-clean Message: begin with creating a flake8 tox env -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sun Feb 22 13:21:35 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 12:21:35 -0000 Subject: [Pytest-commit] commit/pytest: 4 new changesets Message-ID: <20150222122135.31195.47191@app08.ash-private.bitbucket.org> 4 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/932e9cd5598d/ Changeset: 932e9cd5598d Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 12:04:57+00:00 Summary: restructure and flake8 clean pytest.py Affected #: 1 file diff -r 52f65c68c647c2addce892b9c93a45fbfb477e11 -r 932e9cd5598d54b00d252d9f3b7550b52c75aa09 pytest.py --- a/pytest.py +++ b/pytest.py @@ -2,17 +2,16 @@ """ pytest: unit and functional testing with Python. """ -__all__ = ['main'] - -if __name__ == '__main__': # if run as a script or by 'python -m pytest' - # we trigger the below "else" condition by the following import - import pytest - raise SystemExit(pytest.main()) - -# else we are imported from _pytest.config import main, UsageError, _preloadplugins, cmdline from _pytest import __version__ +import pytest -_preloadplugins() # to populate pytest.* namespace so help(pytest) works +__all__ = ['main', 'UsageError', 'cmdline', '__version__'] +if __name__ == '__main__': + # if run as a script or by 'python -m pytest' + raise SystemExit(pytest.main()) +else: + # we are imported, populate pytest.* namespace so help(pytest) works + _preloadplugins() https://bitbucket.org/hpk42/pytest/commits/dcd4cf8805c0/ Changeset: dcd4cf8805c0 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 12:10:15+00:00 Summary: flake8 clean setup.py Affected #: 1 file diff -r 932e9cd5598d54b00d252d9f3b7550b52c75aa09 -r dcd4cf8805c0650288d8db314b8f5ac3abb82054 setup.py --- a/setup.py +++ b/setup.py @@ -1,4 +1,5 @@ -import os, sys +import os +import sys from setuptools import setup, Command classifiers = ['Development Status :: 6 - Mature', @@ -10,8 +11,8 @@ 'Topic :: Software Development :: Testing', 'Topic :: Software Development :: Libraries', 'Topic :: Utilities'] + [ - ('Programming Language :: Python :: %s' % x) for x in - '2 2.6 2.7 3 3.2 3.3 3.4'.split()] + ('Programming Language :: Python :: %s' % x) + for x in '2 2.6 2.7 3 3.2 3.3 3.4'.split()] long_description = open('README.rst').read() @@ -31,7 +32,8 @@ url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], - author='Holger Krekel, Benjamin Peterson, Ronny Pfannschmidt, Floris Bruynooghe and others', + author='Holger Krekel, Benjamin Peterson,' + ' Ronny Pfannschmidt, Floris Bruynooghe and others', author_email='holger at merlinux.eu', entry_points=make_entry_points(), classifiers=classifiers, @@ -51,8 +53,8 @@ else: if basename.startswith('pypy'): points = {'py.test-%s' % basename: target} - else: # cpython - points = {'py.test-%s.%s' % versioninfo[:2] : target} + else: # cpython + points = {'py.test-%s.%s' % versioninfo[:2]: target} points['py.test'] = target return points @@ -68,10 +70,13 @@ class PyTest(Command): user_options = [] + def initialize_options(self): pass + def finalize_options(self): pass + def run(self): import subprocess PPATH = [x for x in os.environ.get('PYTHONPATH', '').split(':') if x] https://bitbucket.org/hpk42/pytest/commits/6dc46b43b7cb/ Changeset: 6dc46b43b7cb Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 12:20:47+00:00 Summary: flake8 clean core Affected #: 1 file diff -r dcd4cf8805c0650288d8db314b8f5ac3abb82054 -r 6dc46b43b7cb57dc77d6b33d6400f74518cacbda _pytest/core.py --- a/_pytest/core.py +++ b/_pytest/core.py @@ -7,10 +7,12 @@ import py # don't import pytest to avoid circular imports -assert py.__version__.split(".")[:2] >= ['1', '4'], ("installation problem: " +assert py.__version__.split(".")[:2] >= ['1', '4'], ( + "installation problem: " "%s is too old, remove or upgrade 'py'" % (py.__version__)) -py3 = sys.version_info > (3,0) +py3 = sys.version_info > (3, 0) + class TagTracer: def __init__(self): @@ -32,7 +34,7 @@ indent = " " * self.indent lines = [ - "%s%s [%s]\n" %(indent, content, ":".join(tags)) + "%s%s [%s]\n" % (indent, content, ":".join(tags)) ] for name, value in extra.items(): @@ -58,14 +60,18 @@ assert isinstance(tags, tuple) self._tag2proc[tags] = processor + class TagTracerSub: def __init__(self, root, tags): self.root = root self.tags = tags + def __call__(self, *args): self.root.processmessage(self.tags, args) + def setmyprocessor(self, processor): self.root.setprocessor(self.tags, processor) + def get(self, name): return self.__class__(self.root, self.tags + (name,)) @@ -82,6 +88,7 @@ """ name = wrapper_func.__name__ oldcall = getattr(cls, name) + def wrap_exec(*args, **kwargs): gen = wrapper_func(*args, **kwargs) return wrapped_call(gen, lambda: oldcall(*args, **kwargs)) @@ -89,10 +96,12 @@ setattr(cls, name, wrap_exec) return lambda: setattr(cls, name, oldcall) + def raise_wrapfail(wrap_controller, msg): co = wrap_controller.gi_code raise RuntimeError("wrap_controller at %r %s:%d %s" % - (co.co_name, co.co_filename, co.co_firstlineno, msg)) + (co.co_name, co.co_filename, co.co_firstlineno, msg)) + def wrapped_call(wrap_controller, func): """ Wrap calling to a function with a generator which needs to yield @@ -118,6 +127,7 @@ Calling the ``get_result`` method will return the result or reraise the exception raised when the function was called. """ excinfo = None + def __init__(self, func): try: self.result = func() @@ -181,9 +191,9 @@ return name = name or getattr(plugin, '__name__', str(id(plugin))) if self.isregistered(plugin, name): - raise ValueError("Plugin already registered: %s=%s\n%s" %( + raise ValueError("Plugin already registered: %s=%s\n%s" % ( name, plugin, self._name2plugin)) - #self.trace("registering", name, plugin) + # self.trace("registering", name, plugin) reg = getattr(self, "_registercallback", None) if reg is not None: reg(plugin, name) # may call addhooks @@ -267,7 +277,7 @@ try: from pkg_resources import iter_entry_points, DistributionNotFound except ImportError: - return # XXX issue a warning + return # XXX issue a warning for ep in iter_entry_points('pytest11'): name = ep.name if name.startswith("pytest_"): @@ -282,7 +292,7 @@ self.register(plugin, name=name) 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) @@ -325,9 +335,10 @@ except: e = sys.exc_info()[1] import pytest - if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception): + if not hasattr(pytest, 'skip') or \ + not isinstance(e, pytest.skip.Exception): raise - self._warnings.append("skipped plugin %r: %s" %((modname, e.msg))) + self._warnings.append("skipped plugin %r: %s" % ((modname, e.msg))) else: self.register(mod, modname) self.consider_module(mod) @@ -356,8 +367,9 @@ return l def call_plugin(self, plugin, methname, kwargs): - return MultiCall(methods=self.listattr(methname, plugins=[plugin]), - kwargs=kwargs, firstresult=True).execute() + return MultiCall( + methods=self.listattr(methname, plugins=[plugin]), + kwargs=kwargs, firstresult=True).execute() def importplugin(importspec): @@ -370,6 +382,7 @@ __import__(importspec) return sys.modules[importspec] + class MultiCall: """ execute a call into multiple python functions/methods. """ @@ -381,8 +394,9 @@ self.firstresult = firstresult def __repr__(self): - status = "%d results, %d meths" % (len(self.results), len(self.methods)) - return "" %(status, self.kwargs) + status = "%d results, %d meths" % \ + (len(self.results), len(self.methods)) + return "" % (status, self.kwargs) def execute(self): all_kwargs = self.kwargs @@ -400,7 +414,7 @@ return self.results -def varnames(func, startindex=None): +def varnames(func, startindex=None): # noqa - complexity 13 """ return argument name tuple for a function, method, class or callable. In case of a class, its "__init__" method is considered. @@ -460,9 +474,9 @@ argnames=varnames(method, startindex=isclass)) setattr(self, name, hc) added = True - #print ("setting new hook", name) + # print ("setting new hook", name) if not added: - raise ValueError("did not find new %r hooks in %r" %( + raise ValueError("did not find new %r hooks in %r" % ( prefix, hookspec,)) def _getcaller(self, name, plugins): @@ -475,7 +489,7 @@ def _scan_plugin(self, plugin): def fail(msg, *args): name = getattr(plugin, '__name__', plugin) - raise PluginValidationError("plugin %r\n%s" %(name, msg % args)) + raise PluginValidationError("plugin %r\n%s" % (name, msg % args)) for name in dir(plugin): if not name.startswith(self.prefix): @@ -493,7 +507,7 @@ "actual definition: %s\n" "available hookargs: %s", arg, formatdef(method), - ", ".join(hook.argnames)) + ", ".join(hook.argnames)) yield hook @@ -512,7 +526,7 @@ argnames=self.argnames, methods=methods) def __repr__(self): - return "" %(self.name,) + return "" % (self.name,) def scan_methods(self): self.methods = self.hookrelay._pm.listattr(self.name) @@ -531,13 +545,14 @@ class PluginValidationError(Exception): """ plugin failed validation. """ + def isgenerichook(name): return name == "pytest_plugins" or \ name.startswith("pytest_funcarg__") + def formatdef(func): return "%s%s" % ( func.__name__, inspect.formatargspec(*inspect.getargspec(func)) ) - https://bitbucket.org/hpk42/pytest/commits/605bc8fa35f9/ Changeset: 605bc8fa35f9 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 12:21:19+00:00 Summary: typo Affected #: 1 file diff -r 6dc46b43b7cb57dc77d6b33d6400f74518cacbda -r 605bc8fa35f9d9156aa5c404c3d750ddd3b9f8c2 tox.ini --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,7 @@ [testenv:flake8] changedir= -deps = flake9 +deps = flake8 commands = flake8 {posargs:_pytest testing pytest.py setup.py} [testenv:py27-xdist] Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 13:29:41 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 12:29:41 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 378 Message-ID: <20150222122908.99366.16165@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/378 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3855:605bc8fa35f9 Author : Ronny Pfannschmidt Branch : flake8-clean Message: typo -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sun Feb 22 14:27:52 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 13:27:52 -0000 Subject: [Pytest-commit] commit/pytest: 3 new changesets Message-ID: <20150222132752.20315.80880@app08.ash-private.bitbucket.org> 3 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/70703aae8a84/ Changeset: 70703aae8a84 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 12:50:00+00:00 Summary: flake8 clean _pytest/assertion Affected #: 4 files diff -r 605bc8fa35f9d9156aa5c404c3d750ddd3b9f8c2 -r 70703aae8a84684ae8bc4da981e0a036178a6a00 _pytest/assertion/reinterpret.py --- a/_pytest/assertion/reinterpret.py +++ b/_pytest/assertion/reinterpret.py @@ -5,7 +5,7 @@ class AssertionError(BuiltinAssertionError): - def __init__(self, *args): + def __init__(self, *args): # noqa too complex BuiltinAssertionError.__init__(self, *args) if args: # on Python2.6 we get len(args)==2 for: assert 0, (x,y) diff -r 605bc8fa35f9d9156aa5c404c3d750ddd3b9f8c2 -r 70703aae8a84684ae8bc4da981e0a036178a6a00 _pytest/assertion/rewrite.py --- a/_pytest/assertion/rewrite.py +++ b/_pytest/assertion/rewrite.py @@ -13,6 +13,7 @@ import py from _pytest.assertion import util +_format_explanation = util.format_explanation # noqa # pytest caches rewritten pycs in __pycache__. @@ -35,6 +36,7 @@ REWRITE_NEWLINES = sys.version_info[:2] != (2, 7) and sys.version_info < (3, 2) ASCII_IS_DEFAULT_ENCODING = sys.version_info[0] < 3 + class AssertionRewritingHook(object): """PEP302 Import hook which rewrites asserts.""" @@ -47,7 +49,7 @@ self.fnpats = session.config.getini("python_files") self.session = session - def find_module(self, name, path=None): + def find_module(self, name, path=None): # noqa too complex if self.session is None: return None sess = self.session @@ -162,8 +164,6 @@ raise return sys.modules[name] - - def is_package(self, name): try: fd, fn, desc = imp.find_module(name) @@ -202,7 +202,7 @@ 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. @@ -223,7 +223,8 @@ cookie_re = re.compile(r"^[ \t\f]*#.*coding[:=][ \t]*[-\w.]+") BOM_UTF8 = '\xef\xbb\xbf' -def _rewrite_test(state, fn): + +def _rewrite_test(state, fn): # noqa: too complex """Try to read and rewrite *fn* and return the code object.""" try: stat = fn.stat() @@ -245,8 +246,8 @@ end1 = source.find("\n") 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[0:end1]) is None and + cookie_re.match(source[end1 + 1:end2]) is None): if hasattr(state, "_indecode"): # encodings imported us again, so don't rewrite. return None, None @@ -279,6 +280,7 @@ 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"): @@ -292,6 +294,7 @@ 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. @@ -349,8 +352,6 @@ return repr.replace(t("\n"), t("\\n")) -from _pytest.assertion.util import format_explanation as _format_explanation # noqa - def _format_assertmsg(obj): """Format the custom assertion message given. @@ -378,9 +379,11 @@ 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): @@ -389,6 +392,7 @@ 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: @@ -422,7 +426,7 @@ ast.Mult: "*", ast.Div: "/", ast.FloorDiv: "//", - ast.Mod: "%%", # escaped for string formatting + ast.Mod: "%%", # escaped for string formatting ast.Eq: "==", ast.NotEq: "!=", ast.Lt: "<", @@ -502,7 +506,7 @@ """ - def run(self, mod): + def run(self, mod): # noqa: too complex """Find all assert statements in *mod* and rewrite them.""" if not mod.body: # Nothing to do. @@ -701,11 +705,12 @@ levels = len(boolop.values) - 1 self.push_format_context() # Process each operand, short-circuting if needed. + cond = None for i, v in enumerate(boolop.values): 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, [])) self.on_failure = fail_inner self.push_format_context() res, expl = self.visit(v) diff -r 605bc8fa35f9d9156aa5c404c3d750ddd3b9f8c2 -r 70703aae8a84684ae8bc4da981e0a036178a6a00 _pytest/assertion/util.py --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -122,18 +122,24 @@ basestring = str -def assertrepr_compare(config, op, left, right): +def assertrepr_compare(config, op, left, right): # noqa too complex """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)) summary = u('%s %s %s') % (left_repr, op, 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 istext(x) + + 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: @@ -176,7 +182,7 @@ return [summary] + explanation -def _diff_text(left, right, verbose=False): +def _diff_text(left, right, verbose=False): # noqa too complex """Return the explanation for the diff between text or bytes Unless --verbose is used this will skip leading and trailing @@ -244,8 +250,8 @@ explanation += [ u('Right contains more items, first extra item: %s') % py.io.saferepr(right[len(left)],)] - return explanation # + _diff_text(pprint.pformat(left), - # pprint.pformat(right)) + # explanation += _diff_text(pprint.pformat(left), pprint.pformat(right)) + return explanation def _compare_eq_set(left, right, verbose=False): diff -r 605bc8fa35f9d9156aa5c404c3d750ddd3b9f8c2 -r 70703aae8a84684ae8bc4da981e0a036178a6a00 tox.ini --- a/tox.ini +++ b/tox.ini @@ -145,3 +145,5 @@ [flake8] max-complexity = 10 +exclude = _pytest/assertion/oldinterpret.py,_pytest/assertion/newinterpret.py + https://bitbucket.org/hpk42/pytest/commits/509d62feb916/ Changeset: 509d62feb916 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 13:25:03+00:00 Summary: flake8 clean _pytest/python Affected #: 1 file diff -r 70703aae8a84684ae8bc4da981e0a036178a6a00 -r 509d62feb91604048b1af64ce23b7e1cd563c0c8 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -18,6 +18,7 @@ # used to work around a python2 exception info leak exc_clear = getattr(sys, 'exc_clear', lambda: None) + def getfslineno(obj): # xxx let decorators etc specify a sane ordering while hasattr(obj, "__wrapped__"): @@ -28,6 +29,7 @@ assert isinstance(fslineno[1], int), obj return fslineno + def getimfunc(func): try: return func.__func__ @@ -50,7 +52,7 @@ 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 @@ -82,14 +84,15 @@ they will be generated automatically from the params. """ - 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)(scope) + "function", params, autouse)(scope) if params is not None and not isinstance(params, (list, tuple)): params = list(params) return FixtureFunctionMarker(scope, params, autouse, ids=ids) + def yield_fixture(scope="function", params=None, autouse=False, ids=None): """ (return a) decorator to mark a yield-fixture factory function (EXPERIMENTAL). @@ -99,16 +102,17 @@ statement to provide a fixture. See http://pytest.org/en/latest/yieldfixture.html for more info. """ - 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, yieldctx=True)(scope) + "function", params, autouse, yieldctx=True)(scope) else: return FixtureFunctionMarker(scope, params, autouse, yieldctx=True, ids=ids) defaultfuncargprefixmarker = fixture() + def pyobj_property(name): def get(self): node = self.getparent(getattr(pytest, name)) @@ -121,20 +125,26 @@ 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") - parser.addini("usefixtures", type="args", default=[], + group.addoption( + '--fixtures', '--funcargs', + action="store_true", dest="showfixtures", default=False, + help="show available fixtures, sorted by plugin appearance") + parser.addini( + "usefixtures", type="args", default=[], help="list of default fixtures to be used with this project") - parser.addini("python_files", type="args", + 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",], + 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",], + parser.addini( + "python_functions", type="args", default=["test"], help="prefixes or glob names for Python test function and " "method discovery") + def pytest_cmdline_main(config): if config.option.showfixtures: showfixtures(config) @@ -149,8 +159,10 @@ for marker in markers: metafunc.parametrize(*marker.args, **marker.kwargs) + def pytest_configure(config): - config.addinivalue_line("markers", + 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 " @@ -160,27 +172,36 @@ "see http://pytest.org/latest/parametrize.html for more info and " "examples." ) - config.addinivalue_line("markers", + config.addinivalue_line( + "markers", "usefixtures(fixturename1, fixturename2, ...): mark tests as needing " - "all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures " + "all of the specified fixtures. " + "see http://pytest.org/latest/fixture.html#usefixtures " ) + def pytest_sessionstart(session): session._fixturemanager = FixtureManager(session) + @pytest.mark.trylast def pytest_namespace(): raises.Exception = pytest.fail.Exception return { 'fixture': fixture, 'yield_fixture': yield_fixture, - 'raises' : raises, + 'raises': raises, 'collect': { - 'Module': Module, 'Class': Class, 'Instance': Instance, - 'Function': Function, 'Generator': Generator, - '_fillfuncargs': fillfixtures} + 'Module': Module, + 'Class': Class, + 'Instance': Instance, + 'Function': Function, + 'Generator': Generator, + '_fillfuncargs': fillfixtures, + }, } + @fixture(scope="session") def pytestconfig(request): """ the pytest config object with access to command line opts.""" @@ -200,6 +221,7 @@ testfunction(**testargs) return True + def pytest_collect_file(path, parent): ext = path.ext if ext == ".py": @@ -208,13 +230,15 @@ 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) + @pytest.mark.hookwrapper def pytest_pycollect_makeitem(collector, name, obj): outcome = yield @@ -227,13 +251,15 @@ Class = collector._getcustomclass("Class") outcome.force_result(Class(name, parent=collector)) elif collector.funcnamefilter(name) and hasattr(obj, "__call__") and\ - getfixturemarker(obj) is None: + getfixturemarker(obj) is None: # mock seems to store unbound methods (issue473), normalize it obj = getattr(obj, "__func__", obj) if not isfunction(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) + if getattr(obj, "__test__", True): if is_generator(obj): res = Generator(name, parent=collector) @@ -241,18 +267,21 @@ res = list(collector._genfunctions(name, obj)) outcome.force_result(res) + def is_generator(func): try: - return py.code.getrawcode(func).co_flags & 32 # generator function - except AttributeError: # builtin functions have no bytecode + return py.code.getrawcode(func).co_flags & 32 # generator function + except AttributeError: # builtin functions have no bytecode # assume them to not be generators return False + class PyobjContext(object): module = pyobj_property("Module") cls = pyobj_property("Class") instance = pyobj_property("Instance") + class PyobjMixin(PyobjContext): def obj(): def fget(self): @@ -261,6 +290,7 @@ except AttributeError: self._obj = obj = self._getobj() return obj + def fset(self, value): self._obj = value return property(fget, fset, None, "underlying python object") @@ -308,6 +338,7 @@ assert isinstance(lineno, int) return fspath, lineno, modpath + class PyCollector(PyobjMixin, pytest.Collector): def funcnamefilter(self, name): @@ -358,7 +389,7 @@ 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) @@ -387,11 +418,12 @@ add_funcarg_pseudo_fixture_def(self, metafunc, fm) for callspec in metafunc._calls: - subname = "%s[%s]" %(name, callspec.id) + subname = "%s[%s]" % (name, callspec.id) yield Function(name=subname, parent=self, callspec=callspec, callobj=funcobj, fixtureinfo=fixtureinfo, - keywords={callspec.id:True}) + keywords={callspec.id: True}) + def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager): # this function will transform all collected calls to a functions @@ -401,7 +433,7 @@ # 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 = {} @@ -437,10 +469,11 @@ 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 @@ -449,12 +482,14 @@ def get_direct_param_fixture_func(request): return request.param + class FuncFixtureInfo: def __init__(self, argnames, names_closure, name2fixturedefs): self.argnames = argnames self.names_closure = names_closure self.name2fixturedefs = name2fixturedefs + def transfer_markers(funcobj, cls, mod): # XXX this should rather be code in the mark plugin or the mark # plugin should merge with the python plugin. @@ -469,6 +504,7 @@ else: pytestmark(funcobj) + class Module(pytest.File, PyCollector): """ Collector for test classes and functions. """ def _getobj(self): @@ -495,9 +531,9 @@ " %s\n" "HINT: remove __pycache__ / .pyc files and/or use a " "unique basename for your test file modules" - % e.args + % e.args ) - #print "imported test module", mod + # print "imported test module", mod self.config.pluginmanager.consider_module(mod) return mod @@ -506,7 +542,7 @@ if setup_module is None: setup_module = xunitsetup(self.obj, "setup_module") if setup_module is not None: - #XXX: nose compat hack, move to nose plugin + # XXX: nose compat hack, move to nose plugin # if it takes a positional arg, its probably a pytest style one # so we pass the current module object if inspect.getargspec(setup_module)[0]: @@ -517,14 +553,13 @@ if fin is None: fin = getattr(self.obj, 'teardown_module', None) if fin is not None: - #XXX: nose compat hack, move to nose plugin + # XXX: nose compat hack, move to nose plugin # if it takes a positional arg, it's probably a pytest style one # so we pass the current module object if inspect.getargspec(fin)[0]: - finalizer = lambda: fin(self.obj) + self.addfinalizer(lambda: fin(self.obj)) else: - finalizer = fin - self.addfinalizer(finalizer) + self.addfinalizer(fin) class Class(PyCollector): @@ -532,7 +567,7 @@ def collect(self): 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 [] return [self._getcustomclass("Instance")(name="()", parent=self)] @@ -549,6 +584,7 @@ fin_class = getattr(fin_class, '__func__', fin_class) self.addfinalizer(lambda: fin_class(self.obj)) + class Instance(PyCollector): def _getobj(self): obj = self.parent.obj() @@ -562,6 +598,7 @@ self.obj = self._getobj() return self.obj + class FunctionMixin(PyobjMixin): """ mixin for the code common to Function and Generator. """ @@ -610,8 +647,8 @@ if excinfo.errisinstance(pytest.fail.Exception): if not excinfo.value.pytrace: return str(excinfo.value) - return super(FunctionMixin, self)._repr_failure_py(excinfo, - style=style) + return super(FunctionMixin, self)._repr_failure_py( + excinfo, style=style) def repr_failure(self, excinfo, outerr=None): assert outerr is None, "XXX outerr usage is deprecated" @@ -634,13 +671,16 @@ 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)) return l @@ -665,7 +705,6 @@ return True - def fillfixtures(function): """ fill missing funcargs for a test function. """ try: @@ -690,6 +729,7 @@ _notexists = object() + class CallSpec2(object): def __init__(self, metafunc): self.metafunc = metafunc @@ -718,7 +758,7 @@ 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: @@ -734,7 +774,7 @@ def setmulti(self, valtype, argnames, valset, id, keywords, scopenum, param_index): - for arg,val in zip(argnames, valset): + for arg, val in zip(argnames, valset): self._checkargnotcontained(arg) getattr(self, valtype)[arg] = val self.indices[arg] = param_index @@ -766,6 +806,7 @@ """ alias attribute for ``fixturenames`` for pre-2.3 compatibility""" return self.fixturenames + class Metafunc(FuncargnamesCompatAttr): def __init__(self, function, fixtureinfo, config, cls=None, module=None): self.config = config @@ -779,7 +820,7 @@ self._ids = py.builtin.set() 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 @@ -803,9 +844,9 @@ :arg ids: list of string ids, or a callable. If strings, each is corresponding to the argvalues so that they are part of the test id. - If callable, it should take one argument (a single argvalue) and return - a string or return None. If None, the automatically generated id for that - argument will be used. + If callable, it should take one argument (a single argvalue) + and return a string or return None. If None, + the automatically generated id for that argument will be used. If no ids are provided they will be generated automatically from the argvalues. @@ -841,10 +882,10 @@ scope = "function" scopenum = scopes.index(scope) if not indirect: - #XXX should we also check for the opposite case? + # XXX should we also check for the opposite case? for arg in argnames: if arg not in self.fixturenames: - raise ValueError("%r uses no fixture %r" %( + raise ValueError("%r uses no fixture %r" % ( self.function, arg)) valtype = indirect and "params" or "funcargs" idfn = None @@ -852,7 +893,7 @@ idfn = ids ids = None if ids and len(ids) != len(argvalues): - raise ValueError('%d tests specified with %d ids' %( + raise ValueError('%d tests specified with %d ids' % ( len(argvalues), len(ids))) if not ids: ids = idmaker(argnames, argvalues, idfn) @@ -861,9 +902,10 @@ for param_index, valset in enumerate(argvalues): assert len(valset) == len(argnames) newcallspec = callspec.copy(self) - newcallspec.setmulti(valtype, argnames, valset, ids[param_index], - newkeywords.get(param_index, {}), scopenum, - param_index) + newcallspec.setmulti( + valtype, argnames, valset, ids[param_index], + newkeywords.get(param_index, {}), scopenum, + param_index) newcalls.append(newcallspec) self._calls = newcalls @@ -880,8 +922,8 @@ :arg id: used for reporting and identification purposes. If you don't supply an `id` an automatic unique id will be generated. - :arg param: a parameter which will be exposed to a later fixture function - invocation through the ``request.param`` attribute. + :arg param: a parameter which will be exposed to a later fixture + function invocation through the ``request.param`` attribute. """ assert funcargs is None or isinstance(funcargs, dict) if funcargs is not None: @@ -914,13 +956,15 @@ pass if isinstance(val, (float, int, str, bool, NoneType)): return str(val) - return str(argname)+str(idx) + return str(argname) + str(idx) + def _idvalset(idx, valset, argnames, idfn): this_id = [_idval(val, argname, idx, idfn) for val, argname in zip(valset, argnames)] return "-".join(this_id) + def idmaker(argnames, argvalues, idfn=None): ids = [_idvalset(valindex, valset, argnames, idfn) for valindex, valset in enumerate(argvalues)] @@ -929,10 +973,12 @@ ids = [str(i) + testid for i, testid in enumerate(ids)] return ids + def showfixtures(config): from _pytest.main import wrap_session return wrap_session(config, _showfixtures_main) + def _showfixtures_main(config, session): session.perform_collect() curdir = py.path.local() @@ -967,12 +1013,12 @@ 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) @@ -982,8 +1028,8 @@ for line in doc.split("\n"): tw.line(" " + line.strip()) else: - tw.line(" %s: no docstring available" %(loc,), - red=True) + tw.line(" %s: no docstring available" % (loc,), red=True) + def getlocation(function, curdir): import inspect @@ -991,10 +1037,11 @@ 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) # builtin pytest.raises helper + def raises(ExpectedException, *args, **kwargs): """ assert that a code block/function call raises @ExpectedException and raise a failure exception otherwise. @@ -1067,7 +1114,7 @@ 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 = py.code.Source(code).compile() py.builtin.exec_(code, frame.f_globals, loc) @@ -1083,6 +1130,7 @@ return py.code.ExceptionInfo() pytest.fail("DID NOT RAISE") + class RaisesContext(object): def __init__(self, ExpectedException): self.ExpectedException = ExpectedException @@ -1103,11 +1151,13 @@ # the basic pytest Function item # + class Function(FunctionMixin, pytest.Item, FuncargnamesCompatAttr): """ a Function Item is responsible for setting up and executing a Python test function. """ _genid = None + def __init__(self, name, parent, args=None, config=None, callspec=None, callobj=NOTSET, keywords=None, session=None, fixtureinfo=None): @@ -1153,7 +1203,7 @@ 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) @@ -1178,7 +1228,7 @@ pass else: fs, lineno = self._getfslineno() - pytest.skip("got empty parameter set, function %s at %s:%d" %( + pytest.skip("got empty parameter set, function %s at %s:%d" % ( self.function.__name__, fs, lineno)) super(Function, self).setup() fillfixtures(self) @@ -1190,9 +1240,11 @@ 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__ + def provide(self): if func.__name__ in scope2props[self.scope]: return func(self) @@ -1216,7 +1268,7 @@ self.fixturename = None #: Scope string, one of "function", "cls", "module", "session" self.scope = "function" - self._funcargs = {} + self._funcargs = {} self._fixturedefs = {} fixtureinfo = pyfuncitem._fixtureinfo self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy() @@ -1229,7 +1281,6 @@ """ 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: @@ -1237,7 +1288,7 @@ # getfuncargvalue(argname) usage which was naturally # not known at parsing/collection time fixturedefs = self._fixturemanager.getfixturedefs( - argname, self._pyfuncitem.parent.nodeid) + argname, self._pyfuncitem.parent.nodeid) self._arg2fixturedefs[argname] = fixturedefs # fixturedefs list is immutable so we maintain a decreasing index index = self._arg2index.get(argname, 0) - 1 @@ -1251,7 +1302,6 @@ """ 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. """ @@ -1282,7 +1332,7 @@ @scopeproperty() def fspath(self): - """ the file system path of the test module which collected this test. """ + """ file system path of the test module which collected this test. """ return self._pyfuncitem.fspath @property @@ -1331,7 +1381,8 @@ if argname not in item.funcargs: item.funcargs[argname] = self.getfuncargvalue(argname) - def cached_setup(self, setup, teardown=None, scope="module", extrakey=None): + def cached_setup(self, setup, teardown=None, + scope="module", extrakey=None): """ (deprecated) Return a testing resource managed by ``setup`` & ``teardown`` calls. ``scope`` and ``extrakey`` determine when the ``teardown`` function will be called so that subsequent calls to @@ -1347,7 +1398,7 @@ :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: @@ -1355,9 +1406,10 @@ except KeyError: __tracebackhide__ = True if scopemismatch(self.scope, scope): - raise ScopeMismatchError("You tried to access a %r scoped " - "resource with a %r scoped request object" %( - (scope, self.scope))) + raise ScopeMismatchError( + "You tried to access a %r scoped " + "resource with a %r scoped request object" + % (scope, self.scope)) __tracebackhide__ = False val = setup() cache[cachekey] = val @@ -1437,10 +1489,11 @@ if scopemismatch(self.scope, scope): # try to report something helpful lines = subrequest._factorytraceback() - raise ScopeMismatchError("You tried to access the %r scoped " + raise ScopeMismatchError( + "You tried to access the %r scoped " "fixture %r with a %r scoped request object, " - "involved factories\n%s" %( - (scope, argname, self.scope, "\n".join(lines)))) + "involved factories\n%s" + % (scope, argname, self.scope, "\n".join(lines))) __tracebackhide__ = False # clear sys.exc_info before invoking the fixture (python bug?) @@ -1462,7 +1515,7 @@ fs, lineno = getfslineno(factory) p = self._pyfuncitem.session.fspath.bestrelpath(fs) args = inspect.formatargspec(*inspect.getargspec(factory)) - lines.append("%s:%d: def %s%s" %( + lines.append("%s:%d: def %s%s" % ( p, lineno, factory.__name__, args)) return lines @@ -1478,7 +1531,7 @@ return node def __repr__(self): - return "" %(self.node) + return "" % (self.node) class SubRequest(FixtureRequest): @@ -1494,7 +1547,7 @@ self._fixturedef = fixturedef self.addfinalizer = fixturedef.addfinalizer self._pyfuncitem = request._pyfuncitem - self._funcargs = request._funcargs + self._funcargs = request._funcargs self._fixturedefs = request._fixturedefs self._arg2fixturedefs = request._arg2fixturedefs self._arg2index = request._arg2index @@ -1512,9 +1565,12 @@ scopes = "session module class function".split() scopenum_function = scopes.index("function") + + def scopemismatch(currentscope, newscope): return scopes.index(newscope) > scopes.index(currentscope) + class FixtureLookupError(LookupError): """ could not return a requested Fixture (missing or invalid). """ def __init__(self, argname, request, msg=None): @@ -1530,12 +1586,14 @@ stack.extend(map(lambda x: x.func, self.fixturestack)) msg = self.msg if msg is not None: - stack = stack[:-1] # the last fixture raise an error, let's present - # it at the requesting side + # the last fixture raise an error, let's present + # it at the requesting side + stack = stack[:-1] + for function in stack: fspath, lineno = getfslineno(function) lines, _ = inspect.getsourcelines(function) - 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) @@ -1551,10 +1609,12 @@ if faclist: available.append(name) msg = "fixture %r not found" % (self.argname,) - msg += "\n available fixtures: %s" %(", ".join(available),) + msg += "\n available fixtures: %s" % (", ".join(available),) msg += "\n use 'py.test --fixtures [testpath]' for help on them." - return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname) + return FixtureLookupErrorRepr( + fspath, lineno, tblines, msg, self.argname) + class FixtureLookupErrorRepr(TerminalRepr): def __init__(self, filename, firstlineno, tblines, errorstring, argname): @@ -1565,13 +1625,14 @@ self.argname = argname def toterminal(self, tw): - #tw.line("FixtureLookupError: %s" %(self.argname), red=True) + # tw.line("FixtureLookupError: %s" %(self.argname), red=True) for tbline in self.tblines: tw.line(tbline.rstrip()) for line in self.errorstring.split("\n"): tw.line(" " + line.strip(), red=True) tw.line() - tw.line("%s:%d" % (self.filename, self.firstlineno+1)) + tw.line("%s:%d" % (self.filename, self.firstlineno + 1)) + class FixtureManager: """ @@ -1616,10 +1677,11 @@ self._seenplugins = set() self._holderobjseen = set() self._arg2finish = {} - self._nodeid_and_autousenames = [("", self.config.getini("usefixtures"))] + 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: @@ -1638,8 +1700,8 @@ node) return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs) - ### XXX this hook should be called for historic events like pytest_configure - ### so that we don't have to do the below pytest_configure hook + # XXX this hook should be called for historic events like pytest_configure + # so that we don't have to do the below pytest_configure hook def pytest_plugin_registered(self, plugin): if plugin in self._seenplugins: return @@ -1674,7 +1736,7 @@ 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) @@ -1693,6 +1755,7 @@ parentid = parentnode.nodeid fixturenames_closure = self._getautousenames(parentid) + def merge(otherlist): for arg in otherlist: if arg not in fixturenames_closure: @@ -1715,7 +1778,7 @@ for argname in metafunc.fixturenames: faclist = metafunc._arg2fixturedefs.get(argname) if faclist is None: - continue # will raise FixtureLookupError at setup time + continue # will raise FixtureLookupError at setup time for fixturedef in faclist: if fixturedef.params is not None: metafunc.parametrize(argname, fixturedef.params, @@ -1789,39 +1852,45 @@ def fail_fixturefunc(fixturefunc, msg): fs, lineno = getfslineno(fixturefunc) - location = "%s:%s" % (fs, lineno+1) + location = "%s:%s" % (fs, lineno + 1) source = py.code.Source(fixturefunc) pytest.fail(msg + ":\n\n" + str(source.indent()) + "\n" + location, pytrace=False) + def call_fixture_func(fixturefunc, request, kwargs, yieldctx): if yieldctx: if not is_generator(fixturefunc): - fail_fixturefunc(fixturefunc, + fail_fixturefunc( + fixturefunc, msg="yield_fixture requires yield statement in function") iter = fixturefunc(**kwargs) next = getattr(iter, "__next__", None) if next is None: next = getattr(iter, "next") res = next() + def teardown(): try: next() except StopIteration: pass else: - fail_fixturefunc(fixturefunc, + fail_fixturefunc( + fixturefunc, "yield_fixture function has more than one 'yield'") request.addfinalizer(teardown) else: if is_generator(fixturefunc): - fail_fixturefunc(fixturefunc, + fail_fixturefunc( + fixturefunc, msg="pytest.fixture functions cannot use ``yield``. " "Instead write and return an inner function/generator " "and let the consumer call and iterate over it.") res = fixturefunc(**kwargs) return res + class FixtureDef: """ A container for a factory definition. """ def __init__(self, fixturemanager, baseid, argname, func, scope, params, @@ -1904,6 +1973,7 @@ return ("" % (self.argname, self.scope, self.baseid)) + def num_mock_patch_args(function): """ return number of arguments used up by mock arguments (if any) """ patchings = getattr(function, "patchings", None) @@ -1912,13 +1982,13 @@ 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 inspect.isclass(function) + # assert not inspect.isclass(function) realfunction = function while hasattr(realfunction, "__wrapped__"): realfunction = realfunction.__wrapped__ @@ -1940,6 +2010,7 @@ # down to the lower scopes such as to minimize number of "high scope" # setups and teardowns + def reorder_items(items): argkeys_cache = {} for scopenum in range(0, scopenum_function): @@ -1950,15 +2021,16 @@ 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 @@ -1989,7 +2061,7 @@ 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) @@ -1998,6 +2070,7 @@ return (items_before, items_same, items_other, newignore) return items, None, None, None + def get_parametrized_fixture_keys(item, scopenum): """ return list of keys for all parametrized arguments which match the specified scope. """ @@ -2027,6 +2100,7 @@ if getfixturemarker(meth) is None: return meth + def getfixturemarker(obj): """ return fixturemarker or None if it doesn't exist or raised exceptions.""" @@ -2044,6 +2118,8 @@ 'module': Module, 'function': pytest.Item, } + + def get_scope_node(node, scope): cls = scopename2class.get(scope) if cls is None: https://bitbucket.org/hpk42/pytest/commits/95468cc0bb31/ Changeset: 95468cc0bb31 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 13:27:37+00:00 Summary: missed whitespace in assertion util Affected #: 1 file diff -r 509d62feb91604048b1af64ce23b7e1cd563c0c8 -r 95468cc0bb318ead1f108e9d0f15e33bfa3550c9 _pytest/assertion/util.py --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -57,8 +57,10 @@ end = start + i where = end if explanation[end - 1] == '\n': - explanation = (explanation[:start] + explanation[start+15:end-1] + - explanation[end+1:]) + explanation = ( + explanation[:start] + + explanation[start + 15:end - 1] + + explanation[end + 1:]) where -= 17 return explanation @@ -101,7 +103,7 @@ 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() @@ -110,7 +112,7 @@ 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 @@ -125,8 +127,8 @@ def assertrepr_compare(config, op, left, right): # noqa too complex """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') % (left_repr, op, right_repr) def issequence(x): @@ -301,7 +303,7 @@ 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)] Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 14:36:16 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 13:36:16 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 379 Message-ID: <20150222133557.116379.93987@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/379 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3858:95468cc0bb31 Author : Ronny Pfannschmidt Branch : flake8-clean Message: missed whitespace in assertion util -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sun Feb 22 14:40:24 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 13:40:24 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: flake8 clean terminal Message-ID: <20150222134024.4690.56304@app01.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/702eec88814b/ Changeset: 702eec88814b Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 13:33:45+00:00 Summary: flake8 clean terminal Affected #: 1 file diff -r 95468cc0bb318ead1f108e9d0f15e33bfa3550c9 -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e _pytest/terminal.py --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -10,31 +10,40 @@ 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."), - group._addoption('-q', '--quiet', action="count", - dest="quiet", default=0, help="decrease verbosity."), - group._addoption('-r', - action="store", dest="reportchars", default=None, metavar="chars", - help="show extra test summary info as specified by chars (f)ailed, " - "(E)error, (s)skipped, (x)failed, (X)passed (w)warnings.") - group._addoption('-l', '--showlocals', - action="store_true", dest="showlocals", default=False, - help="show locals in tracebacks (disabled by default).") - group._addoption('--report', - action="store", dest="report", default=None, metavar="opts", - help="(deprecated, use -r)") - 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).") - group._addoption('--fulltrace', '--full-trace', - 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).") + group._addoption( + '-v', '--verbose', action="count", + dest="verbose", default=0, help="increase verbosity."), + group._addoption( + '-q', '--quiet', action="count", + dest="quiet", default=0, help="decrease verbosity."), + group._addoption( + '-r', + action="store", dest="reportchars", default=None, metavar="chars", + help="show extra test summary info as specified by chars (f)ailed, " + "(E)error, (s)skipped, (x)failed, (X)passed (w)warnings.") + group._addoption( + '-l', '--showlocals', + action="store_true", dest="showlocals", default=False, + help="show locals in tracebacks (disabled by default).") + group._addoption( + '--report', + action="store", dest="report", default=None, metavar="opts", + help="(deprecated, use -r)") + 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).") + group._addoption( + '--fulltrace', '--full-trace', + 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).") + def pytest_configure(config): config.option.verbose -= config.option.quiet @@ -46,11 +55,13 @@ reporter.write_line("[traceconfig] " + msg) config.trace.root.setprocessor("pytest:config", mywriter) + def getreportopt(config): reportopts = "" optvalue = config.option.report if optvalue: - py.builtin.print_("DEPRECATED: use -r instead of --report option.", + py.builtin.print_( + "DEPRECATED: use -r instead of --report option.", file=sys.stderr) if optvalue: for setting in optvalue.split(","): @@ -66,6 +77,7 @@ reportopts += char return reportopts + def pytest_report_teststatus(report): if report.passed: letter = "." @@ -77,6 +89,7 @@ letter = "f" return report.outcome, letter, report.outcome.upper() + class WarningReport: def __init__(self, code, message, nodeid=None, fslocation=None): self.code = code @@ -114,9 +127,9 @@ def write_fspath_result(self, fspath, res): if fspath != self.currentfspath: self.currentfspath = fspath - #fspath = self.startdir.bestrelpath(fspath) + # fspath = self.startdir.bestrelpath(fspath) self._tw.line() - #relpath = self.startdir.bestrelpath(fspath) + # relpath = self.startdir.bestrelpath(fspath) self._tw.write(fspath + " ") self._tw.write(res) @@ -208,15 +221,15 @@ 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(str(rep.fspath), *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'): @@ -237,7 +250,7 @@ items = [x for x in report.result if isinstance(x, pytest.Item)] self._numcollected += len(items) if self.hasmarkup: - #self.write_fspath_result(report.fspath, 'E') + # self.write_fspath_result(report.fspath, 'E') self.report_collect() def report_collect(self, final=False): @@ -309,7 +322,7 @@ 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): @@ -333,14 +346,14 @@ 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)) @@ -386,7 +399,8 @@ line = str(fspath) if domain: split = str(domain).split('[') - split[0] = split[0].replace('.', '::') # don't replace '.' in params + # don't replace '.' in params + split[0] = split[0].replace('.', '::') line += "::" + '['.join(split) else: line = "[location]" @@ -397,7 +411,7 @@ fspath, lineno, domain = rep.location return domain else: - return "test session" # XXX? + return "test session" # XXX? def _getcrashline(self, rep): try: @@ -473,13 +487,13 @@ session_duration = time.time() - self._sessionstarttime keys = ("failed passed skipped deselected " - "xfailed xpassed warnings").split() + "xfailed xpassed warnings").split() for key in self.stats.keys(): if key not in keys: keys.append(key) parts = [] for key in keys: - if key: # setup/teardown reports have an empty key, ignore them + if key: # setup/teardown reports have an empty key, ignore them val = self.stats.get(key, None) if val: parts.append("%d %s" % (len(val), key)) @@ -510,6 +524,7 @@ self.write_sep("=", "%d tests deselected by %r" % ( len(self.stats['deselected']), " ".join(l)), bold=True) + def repr_pythonversion(v=None): if v is None: v = sys.version_info @@ -518,6 +533,7 @@ except (TypeError, ValueError): return str(v) + def flatten(l): for x in l: if isinstance(x, (list, tuple)): @@ -525,4 +541,3 @@ yield y else: yield x - Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 14:47:47 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 13:47:47 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 380 Message-ID: <20150222134736.109571.95109@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/380 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3859:702eec88814b Author : Ronny Pfannschmidt Branch : flake8-clean Message: flake8 clean terminal -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sun Feb 22 16:41:08 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 15:41:08 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: finish flake8 clean of _pytest Message-ID: <20150222154108.6958.76939@app02.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/c5689ba15d60/ Changeset: c5689ba15d60 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 15:40:42+00:00 Summary: finish flake8 clean of _pytest Affected #: 27 files diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/assertion/__init__.py --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -113,7 +113,7 @@ config=item.config, op=op, left=left, right=right) for new_expl in hook_result: if new_expl: - if (sum(len(p) for p in new_expl[1:]) > 80*8 + if (sum(len(p) for p in new_expl[1:]) > 80 * 8 and item.config.option.verbose < 2): new_expl[1:] = [py.builtin._totext( 'Detailed information truncated, use "-vv" to show')] diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/assertion/reinterpret.py --- a/_pytest/assertion/reinterpret.py +++ b/_pytest/assertion/reinterpret.py @@ -5,7 +5,7 @@ class AssertionError(BuiltinAssertionError): - def __init__(self, *args): # noqa too complex + def __init__(self, *args): BuiltinAssertionError.__init__(self, *args) if args: # on Python2.6 we get len(args)==2 for: assert 0, (x,y) diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/assertion/rewrite.py --- a/_pytest/assertion/rewrite.py +++ b/_pytest/assertion/rewrite.py @@ -49,7 +49,7 @@ self.fnpats = session.config.getini("python_files") self.session = session - def find_module(self, name, path=None): # noqa too complex + def find_module(self, name, path=None): if self.session is None: return None sess = self.session @@ -224,7 +224,7 @@ BOM_UTF8 = '\xef\xbb\xbf' -def _rewrite_test(state, fn): # noqa: too complex +def _rewrite_test(state, fn): """Try to read and rewrite *fn* and return the code object.""" try: stat = fn.stat() @@ -506,7 +506,7 @@ """ - def run(self, mod): # noqa: too complex + def run(self, mod): """Find all assert statements in *mod* and rewrite them.""" if not mod.body: # Nothing to do. diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/assertion/util.py --- a/_pytest/assertion/util.py +++ b/_pytest/assertion/util.py @@ -124,7 +124,7 @@ basestring = str -def assertrepr_compare(config, op, left, right): # noqa too complex +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)) @@ -184,7 +184,7 @@ return [summary] + explanation -def _diff_text(left, right, verbose=False): # noqa too complex +def _diff_text(left, right, verbose=False): """Return the explanation for the diff between text or bytes Unless --verbose is used this will skip leading and trailing diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/capture.py --- a/_pytest/capture.py +++ b/_pytest/capture.py @@ -126,7 +126,7 @@ 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.mark.hookwrapper @@ -162,6 +162,7 @@ request.node._capfuncarg = c = CaptureFixture(SysCapture) return c + @pytest.fixture def capfd(request): """enables capturing of writes to file descriptors 1 and 2 and makes @@ -182,7 +183,7 @@ def _start(self): self._capture = MultiCapture(out=True, err=True, in_=False, - Capture=self.captureclass) + Capture=self.captureclass) self._capture.start_capturing() def close(self): @@ -219,6 +220,7 @@ class EncodedFile(object): errors = "strict" # possibly needed by py3 code (issue555) + def __init__(self, buffer, encoding): self.buffer = buffer self.encoding = encoding @@ -299,9 +301,11 @@ 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. """ @@ -374,7 +378,8 @@ def writeorg(self, data): """ write to original file descriptor. """ if py.builtin._istext(data): - data = data.encode("utf8") # XXX use encoding of original stream + # XXX use encoding of original stream + data = data.encode("utf8") os.write(self.targetfd_save, data) diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -7,12 +7,14 @@ import py # DON't import pytest here because it causes import cycle troubles -import sys, os -from _pytest import hookspec # the extension point definitions +import sys +import os +# the extension point definitions +from _pytest import hookspec from _pytest.core import PluginManager + # pytest startup -# class ConftestImportFailure(Exception): def __init__(self, path, excinfo): Exception.__init__(self, path, excinfo) @@ -40,33 +42,38 @@ else: return config.hook.pytest_cmdline_main(config=config) + class cmdline: # compatibility namespace main = staticmethod(main) + class UsageError(Exception): """ error in pytest usage or invocation""" _preinit = [] default_plugins = ( - "mark main terminal runner python pdb unittest capture skipping " - "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript " - "junitxml resultlog doctest").split() + "mark main terminal runner python pdb unittest capture skipping " + "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript " + "junitxml resultlog doctest").split() + def _preloadplugins(): assert not _preinit _preinit.append(get_plugin_manager()) + def get_plugin_manager(): if _preinit: return _preinit.pop(0) # subsequent calls to main will create a fresh instance pluginmanager = PytestPluginManager() - pluginmanager.config = Config(pluginmanager) # XXX attr needed? + pluginmanager.config = Config(pluginmanager) # XXX attr needed? for spec in default_plugins: pluginmanager.import_plugin(spec) return pluginmanager + def _prepareconfig(args=None, plugins=None): if args is None: args = sys.argv[1:] @@ -82,11 +89,12 @@ for plugin in plugins: pluginmanager.register(plugin) return pluginmanager.hook.pytest_cmdline_parse( - pluginmanager=pluginmanager, args=args) + pluginmanager=pluginmanager, args=args) except Exception: pluginmanager.ensure_shutdown() raise + class PytestPluginManager(PluginManager): def __init__(self, hookspecs=[hookspec]): super(PytestPluginManager, self).__init__(hookspecs=hookspecs) @@ -101,10 +109,12 @@ self.set_tracing(err.write) def pytest_configure(self, config): - config.addinivalue_line("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.") - config.addinivalue_line("markers", + 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.") for warning in self._warnings: @@ -147,7 +157,7 @@ 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): @@ -185,7 +195,8 @@ 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): @@ -203,7 +214,8 @@ """ register an ini-file option. :name: name of the ini-variable - :type: type of the variable, can be ``pathlist``, ``args`` or ``linelist``. + :type: type of the variable, + can be ``pathlist``, ``args`` or ``linelist``. :default: default value if no ini-file option exists but is queried. The value of ini-variables can be retrieved via a call to @@ -236,7 +248,8 @@ _typ_map = { 'int': int, 'string': str, - } + } + # enable after some grace period for plugin writers TYPE_WARN = False @@ -321,7 +334,7 @@ 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 @@ -401,8 +414,9 @@ class MyOptionParser(argparse.ArgumentParser): def __init__(self, parser): self._parser = parser - argparse.ArgumentParser.__init__(self, usage=parser._usage, - add_help=False, formatter_class=DropShorterLongHelpFormatter) + argparse.ArgumentParser.__init__( + self, usage=parser._usage, add_help=False, + formatter_class=DropShorterLongHelpFormatter) def parse_args(self, args=None, namespace=None): """allow splitting of positional arguments""" @@ -415,6 +429,7 @@ getattr(args, FILE_OR_DIR).extend(argv) return args + class DropShorterLongHelpFormatter(argparse.HelpFormatter): """shorten help for long options that differ only in extra hyphens @@ -426,18 +441,19 @@ """ 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: return res options = orgstr.split(', ') - if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2): + if len(options) == 2 and \ + (len(options[0]) == 2 or len(options[1]) == 2): # a shortcut for '-h, --help' or '--abc', '-a' action._formatted_action_invocation = orgstr return orgstr return_list = [] - option_map = getattr(action, 'map_long_option', {}) + option_map = getattr(action, 'map_long_option', {}) if option_map is None: option_map = {} short_long = {} @@ -455,7 +471,7 @@ 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('-', '')): @@ -484,7 +500,7 @@ """ current = py.path.local() self._confcutdir = current.join(namespace.confcutdir, abs=True) \ - if namespace.confcutdir else None + if namespace.confcutdir else None testpaths = namespace.file_or_dir foundanchor = False for path in testpaths: @@ -494,7 +510,7 @@ 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: @@ -561,12 +577,16 @@ except KeyError: pass + class CmdOptions(object): """ holds cmdline options as attributes.""" + def __init__(self, **kwargs): self.__dict__.update(kwargs) + def __repr__(self): - return "" %(self.__dict__,) + return "" % (self.__dict__,) + class Notset: def __repr__(self): @@ -574,12 +594,15 @@ notset = Notset() FILE_OR_DIR = 'file_or_dir' + + class Config(object): """ access to configuration values, pluginmanager and plugin hooks. """ def __init__(self, pluginmanager): #: access to command line option as attributes. - #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead + #: (deprecated), use + #: :py:func:`getoption() <_pytest.config.Config.getoption>` instead self.option = CmdOptions() _a = FILE_OR_DIR self._parser = Parser( @@ -646,7 +669,8 @@ style = "long" else: style = "native" - excrepr = excinfo.getrepr(funcargs=True, + excrepr = excinfo.getrepr( + funcargs=True, showlocals=getattr(option, 'showlocals', False), style=style, ) @@ -654,10 +678,9 @@ 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() - @classmethod def fromdictargs(cls, option_dict, args): """ constructor useable for subprocesses. """ @@ -670,7 +693,7 @@ return config def _onimportconftest(self, conftestmodule): - self.trace("loaded conftestmodule %r" %(conftestmodule,)) + self.trace("loaded conftestmodule %r" % (conftestmodule,)) self.pluginmanager.consider_conftest(conftestmodule) def _processopt(self, opt): @@ -683,7 +706,7 @@ def _getmatchingplugins(self, fspath): return self.pluginmanager._plugins + \ - self._conftest.getconftestmodules(fspath) + self._conftest.getconftestmodules(fspath) def pytest_load_initial_conftests(self, early_config): self._conftest.setinitial(early_config.known_args_namespace) @@ -713,15 +736,15 @@ self.pluginmanager.consider_env() self.known_args_namespace = ns = self._parser.parse_known_args(args) try: - self.hook.pytest_load_initial_conftests(early_config=self, - args=args, parser=self._parser) + self.hook.pytest_load_initial_conftests( + early_config=self, args=args, parser=self._parser) except ConftestImportFailure: e = sys.exc_info()[1] if ns.help or ns.version: # we don't want to prevent --help/--version to work # so just let is pass and print a warning at the end self.pluginmanager._warnings.append( - "could not load initial conftests (%s)\n" % e.path) + "could not load initial conftests (%s)\n" % e.path) else: raise @@ -733,14 +756,15 @@ 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): # 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._preparse(args) # XXX deprecated hook: @@ -756,7 +780,7 @@ 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 `. If the @@ -773,7 +797,7 @@ try: description, type, default = self._parser._inidict[name] except KeyError: - raise ValueError("unknown configuration value: %r" %(name,)) + raise ValueError("unknown configuration value: %r" % (name,)) try: value = self.inicfg[name] except KeyError: @@ -791,7 +815,8 @@ elif type == "args": return shlex.split(value) elif type == "linelist": - return [t for t in map(lambda x: x.strip(), value.split("\n")) if t] + return [t for t in + map(lambda x: x.strip(), value.split("\n")) if t] else: assert type is None return value @@ -830,7 +855,7 @@ 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): @@ -841,12 +866,14 @@ """ (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, inibasenames): args = [x for x in args if not str(x).startswith("-")] if not args: @@ -879,6 +906,6 @@ else: setattr(obj, name, value) obj.__all__.append(name) - #if obj != pytest: + # if obj != pytest: # pytest.__all__.append(name) setattr(pytest, name, value) diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/core.py --- a/_pytest/core.py +++ b/_pytest/core.py @@ -192,7 +192,7 @@ name = name or getattr(plugin, '__name__', str(id(plugin))) if self.isregistered(plugin, name): raise ValueError("Plugin already registered: %s=%s\n%s" % ( - name, plugin, self._name2plugin)) + name, plugin, self._name2plugin)) # self.trace("registering", name, plugin) reg = getattr(self, "_registercallback", None) if reg is not None: @@ -414,7 +414,7 @@ return self.results -def varnames(func, startindex=None): # noqa - complexity 13 +def varnames(func, startindex=None): """ return argument name tuple for a function, method, class or callable. In case of a class, its "__init__" method is considered. @@ -548,7 +548,7 @@ def isgenerichook(name): return name == "pytest_plugins" or \ - name.startswith("pytest_funcarg__") + name.startswith("pytest_funcarg__") def formatdef(func): diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/doctest.py --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -1,41 +1,51 @@ """ discover and run doctests in modules and test files.""" from __future__ import absolute_import import traceback -import pytest, py +import pytest +import py from _pytest.python import FixtureRequest, FuncFixtureInfo from py._code.code import TerminalRepr, ReprFileLocation + def pytest_addoption(parser): - parser.addini('doctest_optionflags', 'option flags for doctests', + parser.addini( + 'doctest_optionflags', 'option flags for doctests', type="args", default=["ELLIPSIS"]) group = parser.getgroup("collect") - group.addoption("--doctest-modules", + group.addoption( + "--doctest-modules", action="store_true", default=False, help="run doctests in all .py modules", dest="doctestmodules") - group.addoption("--doctest-glob", + group.addoption( + "--doctest-glob", action="store", default="test*.txt", metavar="pat", help="doctests file matching pattern, default: test*.txt", dest="doctestglob") + def pytest_collect_file(path, parent): config = parent.config if path.ext == ".py": if config.option.doctestmodules: return DoctestModule(path, parent) - elif (path.ext in ('.txt', '.rst') and parent.session.isinitpath(path)) or \ - path.check(fnmatch=config.getvalue("doctestglob")): + elif (path.ext in ('.txt', '.rst') + and parent.session.isinitpath(path)) or \ + path.check(fnmatch=config.getvalue("doctestglob")): return DoctestTextfile(path, parent) + class ReprFailDoctest(TerminalRepr): def __init__(self, reprlocation, lines): self.reprlocation = reprlocation self.lines = lines + def toterminal(self, tw): for line in self.lines: tw.line(line) self.reprlocation.toterminal(tw) + class DoctestItem(pytest.Item): def __init__(self, name, parent, runner=None, dtest=None): super(DoctestItem, self).__init__(name, parent) @@ -64,23 +74,24 @@ filelines = py.path.local(filename).readlines(cr=0) lines = [] if lineno is not None: - i = max(test.lineno, max(0, lineno - 10)) # XXX? + i = max(test.lineno, max(0, lineno - 10)) # XXX? for line in filelines[i:lineno]: - lines.append("%03d %s" % (i+1, line)) + lines.append("%03d %s" % (i + 1, line)) i += 1 else: - lines.append('EXAMPLE LOCATION UNKNOWN, not showing all tests of that example') + lines.append('EXAMPLE LOCATION UNKNOWN, ' + 'not showing all tests of that example') indent = '>>>' for line in example.source.splitlines(): lines.append('??? %s %s' % (indent, line)) indent = '...' if excinfo.errisinstance(doctest.DocTestFailure): - lines += checker.output_difference(example, - doctestfailure.got, REPORT_UDIFF).split("\n") + lines += checker.output_difference( + example, + doctestfailure.got, REPORT_UDIFF).split("\n") else: inner_excinfo = py.code.ExceptionInfo(excinfo.value.exc_info) - lines += ["UNEXPECTED EXCEPTION: %s" % - repr(inner_excinfo.value)] + lines += ["UNEXPECTED EXCEPTION: %r" % (inner_excinfo.value,)] lines += traceback.format_exception(*excinfo.value.exc_info) return ReprFailDoctest(reprlocation, lines) else: @@ -89,6 +100,7 @@ def reportinfo(self): return self.fspath, None, "[doctest] %s" % self.name + def _get_flag_lookup(): import doctest return dict(DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1, @@ -98,6 +110,7 @@ IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL, COMPARISON_FLAGS=doctest.COMPARISON_FLAGS) + def get_optionflags(parent): optionflags_str = parent.config.getini("doctest_optionflags") flag_lookup_table = _get_flag_lookup() @@ -106,12 +119,14 @@ flag_acc |= flag_lookup_table[flag] return flag_acc + class DoctestTextfile(DoctestItem, pytest.File): def runtest(self): import doctest # satisfy `FixtureRequest` constructor... self.funcargs = {} fm = self.session._fixturemanager + def func(): pass self._fixtureinfo = fm.getfixtureinfo(node=self, func=func, @@ -124,6 +139,7 @@ extraglobs=dict(getfixture=fixture_request.getfuncargvalue), raise_on_error=True, verbose=0) + class DoctestModule(pytest.File): def collect(self): import doctest @@ -138,9 +154,9 @@ doctest_globals = dict(getfixture=fixture_request.getfuncargvalue) # uses internal doctest module parsing mechanism finder = doctest.DocTestFinder() - optionflags= get_optionflags(self) + optionflags = get_optionflags(self) runner = doctest.DebugRunner(verbose=0, optionflags=optionflags) for test in finder.find(module, module.__name__, extraglobs=doctest_globals): - if test.examples: # skip empty doctests + if test.examples: # skip empty doctests yield DoctestItem(test.name, self, runner, test) diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/genscript.py --- a/_pytest/genscript.py +++ b/_pytest/genscript.py @@ -8,11 +8,10 @@ import _pytest - def find_toplevel(name): for syspath in sys.path: base = py.path.local(syspath) - lib = base/name + lib = base / name if lib.check(dir=1): return lib mod = base.join("%s.py" % name) @@ -20,23 +19,28 @@ return mod raise LookupError(name) + def pkgname(toplevel, rootpath, path): parts = path.parts()[len(rootpath.parts()):] return '.'.join([toplevel] + [x.purebasename for x in parts]) + def pkg_to_mapping(name): toplevel = find_toplevel(name) name2src = {} - if toplevel.check(file=1): # module + if toplevel.check(file=1): # module name2src[toplevel.purebasename] = toplevel.read() - else: # package + else: # package for pyfile in toplevel.visit('*.py'): pkg = pkgname(name, toplevel, pyfile) name2src[pkg] = pyfile.read() return name2src + def compress_mapping(mapping): - import base64, pickle, zlib + import base64 + import pickle + import zlib data = pickle.dumps(mapping, 2) data = zlib.compress(data, 9) data = base64.encodestring(data) @@ -50,6 +54,7 @@ mapping.update(pkg_to_mapping(name)) return compress_mapping(mapping) + def generate_script(entry, packages): data = compress_packages(packages) tmpl = py.path.local(__file__).dirpath().join('standalonetemplate.py') @@ -61,16 +66,18 @@ def pytest_addoption(parser): group = parser.getgroup("debugconfig") - group.addoption("--genscript", action="store", default=None, + group.addoption( + "--genscript", action="store", default=None, dest="genscript", metavar="path", help="create standalone pytest script at given target path.") + def pytest_cmdline_main(config): genscript = config.getvalue("genscript") if genscript: tw = py.io.TerminalWriter() - deps = ['py', '_pytest', 'pytest'] - if sys.version_info < (2,7): + deps = ['py', '_pytest', 'pytest'] + if sys.version_info < (2, 7): deps.append("argparse") tw.line("generated script will run on python2.6-python3.3++") else: @@ -121,7 +128,9 @@ path = package for _, name, is_package in pkgutil.iter_modules([path]): if is_package: - for m in _iter_all_modules(os.path.join(path, name), prefix=name + '.'): + for m in _iter_all_modules( + os.path.join(path, name), + prefix=name + '.'): yield prefix + m else: yield prefix + name diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/helpconfig.py --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -1,25 +1,32 @@ """ version info, help messages, tracing configuration. """ import py import pytest -import os, sys +import os +import sys + def pytest_addoption(parser): group = parser.getgroup('debugconfig') - group.addoption('--version', action="store_true", - help="display pytest lib version and import information.") - group._addoption("-h", "--help", action="store_true", 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`.") - group.addoption('--traceconfig', '--trace-config', - 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'.") + group.addoption( + '--version', action="store_true", + help="display pytest lib version and import information.") + group._addoption( + "-h", "--help", action="store_true", 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`.") + group.addoption( + '--traceconfig', '--trace-config', + 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'.") @pytest.mark.hookwrapper @@ -31,19 +38,20 @@ f = open(path, 'w') config._debugfile = f f.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.pluginmanager.set_tracing(f.write) sys.stderr.write("writing pytestdebug information to %s\n" % path) + @pytest.mark.trylast def pytest_unconfigure(config): if hasattr(config, '_debugfile'): config._debugfile.close() sys.stderr.write("wrote pytestdebug information to %s\n" % - config._debugfile.name) + config._debugfile.name) config.trace.root.setwriter(None) @@ -51,7 +59,7 @@ 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: @@ -63,12 +71,13 @@ config.do_unconfigure() return 0 + def showhelp(config): tw = py.io.TerminalWriter() tw.write(config._parser.optparser.format_help()) tw.line() tw.line() - #tw.sep( "=", "config file settings") + # tw.sep( "=", "config file settings") tw.line("[pytest] ini-options in the next " "pytest.ini|tox.ini|setup.cfg file:") tw.line() @@ -78,11 +87,12 @@ 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() ; tw.line() - #tw.sep("=") + tw.line() + tw.line() + # tw.sep("=") tw.line("to see available markers type: py.test --markers") tw.line("to see available fixtures type: py.test --fixtures") tw.line("(shown according to specified file_or_dir or current dir " @@ -96,6 +106,7 @@ ('pytest_plugins', 'list of plugin names to load'), ] + def getpluginversioninfo(config): lines = [] plugininfo = config.pluginmanager._plugin_distinfo @@ -107,11 +118,12 @@ 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__)) + lines.append( + "using: pytest-%s pylib-%s" % (pytest.__version__, py.__version__)) verinfo = getpluginversioninfo(config) if verinfo: @@ -125,7 +137,5 @@ r = plugin.__file__ else: r = repr(plugin) - lines.append(" %-20s: %s" %(name, r)) + lines.append(" %-20s: %s" % (name, r)) return lines - - diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/hookspec.py --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -1,9 +1,11 @@ -""" hook specifications for pytest plugins, invoked from main.py and builtin plugins. """ +""" hook specifications for pytest plugins, +invoked from main.py and builtin plugins. """ # ------------------------------------------------------------------------- # Initialization # ------------------------------------------------------------------------- + def pytest_addhooks(pluginmanager): """called at plugin load time to allow adding new hooks via a call to pluginmanager.registerhooks(module).""" @@ -15,13 +17,16 @@ are parsed. """ + def pytest_cmdline_parse(pluginmanager, args): """return initialized config object, parsing the specified args. """ pytest_cmdline_parse.firstresult = True + def pytest_cmdline_preparse(config, args): """(deprecated) modify command line arguments before option parsing. """ + def pytest_addoption(parser): """register argparse-style options and ini-style config values. @@ -42,28 +47,34 @@ - :py:func:`config.getini(name) <_pytest.config.Config.getini>` to retrieve a value read from an ini-style file. - The config object is passed around on many internal objects via the ``.config`` - attribute or can be retrieved as the ``pytestconfig`` fixture or accessed - via (deprecated) ``pytest.config``. + The config object is passed around on many internal objects + via the ``.config`` attribute or can be retrieved as + the ``pytestconfig`` fixture or + accessed via (deprecated) ``pytest.config``. """ + def pytest_cmdline_main(config): """ called for performing the main command line action. The default implementation will invoke the configure hooks and runtest_mainloop. """ pytest_cmdline_main.firstresult = True + def pytest_load_initial_conftests(args, early_config, parser): """ implements the loading of initial conftest files ahead of command line option parsing. """ + def pytest_configure(config): """ called after command line options have been parsed and all plugins and initial conftest files been loaded. """ + def pytest_unconfigure(config): """ called before test process is exited. """ + def pytest_runtestloop(session): """ called for performing the main runtest loop (after collection finished). """ @@ -73,17 +84,21 @@ # collection hooks # ------------------------------------------------------------------------- + def pytest_collection(session): """ perform the collection protocol for the given session. """ pytest_collection.firstresult = True + 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. """ + def pytest_ignore_collect(path, config): """ return True to prevent considering this path for collection. This hook is consulted for all files and directories prior to calling @@ -91,31 +106,39 @@ """ pytest_ignore_collect.firstresult = True + def pytest_collect_directory(path, parent): """ called before traversing a directory for collection files. """ pytest_collect_directory.firstresult = True + 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. """ + def pytest_make_collect_report(collector): """ perform ``collector.collect()`` and return a CollectReport. """ pytest_make_collect_report.firstresult = True + # ------------------------------------------------------------------------- # Python test function related hooks # ------------------------------------------------------------------------- @@ -128,23 +151,29 @@ """ pytest_pycollect_makemodule.firstresult = True + def pytest_pycollect_makeitem(collector, name, obj): - """ return custom item/collector for a python object in a module, or None. """ + """ return custom item/collector + for a python object in a module, or None. """ pytest_pycollect_makeitem.firstresult = True + def pytest_pyfunc_call(pyfuncitem): """ call underlying test function. """ pytest_pyfunc_call.firstresult = True + def pytest_generate_tests(metafunc): """ generate (multiple) parametrized calls to a test function.""" + # ------------------------------------------------------------------------- # generic runtest related hooks # ------------------------------------------------------------------------- def pytest_itemstart(item, node): """ (deprecated, use pytest_runtest_logstart). """ + def pytest_runtest_protocol(item, nextitem): """ implements the runtest_setup/call/teardown protocol for the given test item, including capturing exceptions and calling @@ -160,15 +189,19 @@ """ pytest_runtest_protocol.firstresult = True + 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``. @@ -178,6 +211,7 @@ so that nextitem only needs to call setup-functions. """ + def pytest_runtest_makereport(item, call): """ return a :py:class:`_pytest.runner.TestReport` object for the given :py:class:`pytest.Item` and @@ -185,6 +219,7 @@ """ pytest_runtest_makereport.firstresult = True + def pytest_runtest_logreport(report): """ process a test setup/call/teardown report relating to the respective phase of executing a test. """ @@ -193,9 +228,11 @@ # test session related hooks # ------------------------------------------------------------------------- + def pytest_sessionstart(session): """ before session.main() is called. """ + def pytest_sessionfinish(session, exitstatus): """ whole test run finishes. """ @@ -217,16 +254,21 @@ # 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.""" + """ return a string to be displayed + as header info for terminal reporting.""" + def pytest_report_teststatus(report): """ return result-category, shortletter and verbose word for reporting.""" pytest_report_teststatus.firstresult = True + def pytest_terminal_summary(terminalreporter): """ add additional section in terminal summary reporting. """ + def pytest_logwarning(message, code, nodeid, fslocation): """ process a warning specified by a message, a code string, a nodeid and fslocation (both of which may be None @@ -236,6 +278,7 @@ # doctest hooks # ------------------------------------------------------------------------- + def pytest_doctest_prepare_content(content): """ return processed content for a given doctest""" pytest_doctest_prepare_content.firstresult = True @@ -244,15 +287,19 @@ # error handling and internal debugging hooks # ------------------------------------------------------------------------- + def pytest_plugin_registered(plugin, manager): """ a new pytest plugin got registered. """ + 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): """ (experimental, new in 2.4) called when an exception was raised which can potentially be @@ -262,5 +309,6 @@ that is not an internal exception like "skip.Exception". """ + def pytest_enter_pdb(): """ called upon pdb.set_trace()""" diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/junitxml.py --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -1,4 +1,5 @@ -""" report test results in JUnit-XML format, for use with Hudson and build integration servers. +""" report test results in JUnit-XML format, +for use with Hudson and build integration servers. Based on initial code from Ross Lawley. """ @@ -16,6 +17,7 @@ unicode = str long = int + class Junit(py.xml.Namespace): pass @@ -32,9 +34,10 @@ (0xE000, 0xFFFD), (0x10000, 0x10FFFF), ) -_legal_xml_re = [unicode("%s-%s") % (unichr(low), unichr(high)) - for (low, high) in _legal_ranges - if low < sys.maxunicode] +_legal_xml_re = [ + unicode("%s-%s") % (unichr(low), unichr(high)) + for (low, high) in _legal_ranges + if low < sys.maxunicode] _legal_xml_re = [unichr(x) for x in _legal_chars] + _legal_xml_re illegal_xml_re = re.compile(unicode('[^%s]') % unicode('').join(_legal_xml_re)) @@ -42,6 +45,7 @@ del _legal_ranges del _legal_xml_re + def bin_xml_escape(arg): def repl(matchobj): i = ord(matchobj.group()) @@ -51,14 +55,18 @@ return unicode('#x%04X') % i return py.xml.raw(illegal_xml_re.sub(repl, py.xml.escape(arg))) + def pytest_addoption(parser): group = parser.getgroup("terminal reporting") - group.addoption('--junitxml', '--junit-xml', action="store", - dest="xmlpath", metavar="path", default=None, - help="create junit-xml style report file at given path.") - group.addoption('--junitprefix', '--junit-prefix', action="store", - metavar="str", default=None, - help="prepend prefix to classnames in junit-xml output") + group.addoption( + '--junitxml', '--junit-xml', action="store", + dest="xmlpath", metavar="path", default=None, + help="create junit-xml style report file at given path.") + group.addoption( + '--junitprefix', '--junit-prefix', action="store", + metavar="str", default=None, + help="prepend prefix to classnames in junit-xml output") + def pytest_configure(config): xmlpath = config.option.xmlpath @@ -67,6 +75,7 @@ config._xml = LogXML(xmlpath, config.option.junitprefix) config.pluginmanager.register(config._xml) + def pytest_unconfigure(config): xml = getattr(config, '_xml', None) if xml: @@ -79,6 +88,7 @@ names[0] = names[0].replace("/", '.') return names + class LogXML(object): def __init__(self, logfile, prefix): logfile = os.path.expanduser(os.path.expandvars(logfile)) @@ -102,11 +112,11 @@ def _write_captured_output(self, report): for capname in ('out', 'err'): allcontent = "" - for name, content in report.get_sections("Captured std%s" % - capname): + for name, content in report.get_sections( + "Captured std%s" % capname): allcontent += content if allcontent: - tag = getattr(Junit, 'system-'+capname) + tag = getattr(Junit, 'system-' + capname) self.append(tag(bin_xml_escape(allcontent))) def append(self, obj): @@ -117,7 +127,7 @@ self._write_captured_output(report) def append_failure(self, report): - #msg = str(report.longrepr.reprtraceback.extraline) + # msg = str(report.longrepr.reprtraceback.extraline) if hasattr(report, "wasxfail"): self.append( Junit.skipped(message="xfail-marked test passes unexpectedly")) @@ -130,13 +140,13 @@ self._write_captured_output(report) def append_collect_error(self, report): - #msg = str(report.longrepr.reprtraceback.extraline) + # msg = str(report.longrepr.reprtraceback.extraline) self.append(Junit.error(bin_xml_escape(report.longrepr), message="collection failure")) self.errors += 1 def append_collect_skipped(self, report): - #msg = str(report.longrepr.reprtraceback.extraline) + # msg = str(report.longrepr.reprtraceback.extraline) self.append(Junit.skipped(bin_xml_escape(report.longrepr), message="collection skipped")) self.skipped += 1 @@ -154,17 +164,16 @@ filename, lineno, skipreason = report.longrepr if skipreason.startswith("Skipped: "): skipreason = bin_xml_escape(skipreason[9:]) - self.append( - Junit.skipped("%s:%s: %s" % (filename, lineno, skipreason), - type="pytest.skip", - message=skipreason - )) + self.append(Junit.skipped( + "%s:%s: %s" % (filename, lineno, skipreason), + type="pytest.skip", message=skipreason, + )) self.skipped += 1 self._write_captured_output(report) def pytest_runtest_logreport(self, report): if report.passed: - if report.when == "call": # ignore setup/teardown + if report.when == "call": # ignore setup/teardown self._opentestcase(report) self.append_pass(report) elif report.failed: @@ -190,9 +199,9 @@ data = bin_xml_escape(excrepr) self.tests.append( Junit.testcase( - Junit.error(data, message="internal error"), - classname="pytest", - name="internal")) + Junit.error(data, message="internal error"), + classname="pytest", + name="internal")) def pytest_sessionstart(self): self.suite_start_time = time.time() @@ -216,4 +225,5 @@ logfile.close() def pytest_terminal_summary(self, terminalreporter): - terminalreporter.write_sep("-", "generated xml file: %s" % (self.logfile)) + terminalreporter.write_sep( + "-", "generated xml file: %s" % (self.logfile)) diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -2,8 +2,11 @@ import re import py -import pytest, _pytest -import os, sys, imp +import pytest +import _pytest +import os +import sys +import imp try: from collections import MutableMapping as MappingMixin except ImportError: @@ -22,54 +25,69 @@ name_re = re.compile("^[a-zA-Z_]\w*$") + def pytest_addoption(parser): - parser.addini("norecursedirs", "directory patterns to avoid for recursion", + parser.addini( + "norecursedirs", "directory patterns to avoid for recursion", type="args", default=['.*', 'CVS', '_darcs', '{arch}', '*.egg']) - #parser.addini("dirpatterns", + # 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_true", default=False, - dest="exitfirst", - 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.") - group._addoption('--strict', action="store_true", - help="run pytest in strict mode, warnings become 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.") + group._addoption( + '-x', '--exitfirst', action="store_true", default=False, + dest="exitfirst", + 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.") + group._addoption( + '--strict', action="store_true", + help="run pytest in strict mode, warnings become 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.") group = parser.getgroup("collect", "collection") - group.addoption('--collectonly', '--collect-only', action="store_true", + group.addoption( + '--collectonly', '--collect-only', action="store_true", help="only collect tests, don't execute them."), - group.addoption('--pyargs', action="store_true", + group.addoption( + '--pyargs', action="store_true", help="try to interpret all arguments as python packages.") - group.addoption("--ignore", action="append", metavar="path", + group.addoption( + "--ignore", action="append", metavar="path", 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, + group.addoption( + '--confcutdir', dest="confcutdir", default=None, metavar="dir", help="only load conftest.py's relative to specified dir.") - group = parser.getgroup("debugconfig", + group = parser.getgroup( + "debugconfig", "test session debugging and configuration") - group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir", - help="base temporary directory for this test run.") + group.addoption( + '--basetemp', dest="basetemp", default=None, metavar="dir", + help="base temporary directory for this test run.") def pytest_namespace(): collect = dict(Item=Item, Collector=Collector, File=File, Session=Session) return dict(collect=collect) + def pytest_configure(config): - pytest.config = config # compatibiltiy + pytest.config = config # compatibiltiy if config.option.exitfirst: config.option.maxfail = 1 + def wrap_session(config, doit): """Skeleton command line program""" session = Session(config) @@ -85,7 +103,7 @@ except pytest.UsageError: args = sys.exc_info()[1].args for msg in args: - sys.stderr.write("ERROR: %s\n" %(msg,)) + sys.stderr.write("ERROR: %s\n" % (msg,)) session.exitstatus = EXIT_USAGEERROR except KeyboardInterrupt: excinfo = py.code.ExceptionInfo() @@ -112,18 +130,22 @@ config.pluginmanager.ensure_shutdown() return session.exitstatus + def pytest_cmdline_main(config): return wrap_session(config, _main) + def _main(config, session): """ default command line protocol for initialization, session, running tests and reporting. """ config.hook.pytest_collection(session=session) config.hook.pytest_runtestloop(session=session) + def pytest_collection(session): return session.perform_collect() + def pytest_runtestloop(session): if session.config.option.collectonly: return True @@ -133,7 +155,7 @@ # keeping sys.exc_info set when calling into a test # python2 keeps sys.exc_info till the frame is left try: - return session.items[i+1] + return session.items[i + 1] except IndexError: return None @@ -144,6 +166,7 @@ raise session.Interrupted(session.shouldstop) return True + def pytest_ignore_collect(path, config): p = path.dirpath() ignore_paths = config._getconftest_pathlist("collect_ignore", path=p) @@ -153,6 +176,7 @@ ignore_paths.extend([py.path.local(x) for x in excludeopt]) return path in ignore_paths + class FSHookProxy(object): def __init__(self, fspath, config): self.fspath = fspath @@ -172,6 +196,7 @@ return property(fget) + class NodeKeywords(MappingMixin): def __init__(self, node): self.node = node @@ -237,14 +262,14 @@ # used for storing artificial fixturedefs for direct parametrization self._name2pseudofixturedef = {} - #self.extrainit() + # self.extrainit() @property def ihook(self): """ fspath sensitive hook proxy used to call pytest hooks""" return self.session.gethookproxy(self.fspath) - #def extrainit(self): + # def extrainit(self): # """"extra initialization after Node is initialized. Implemented # by some subclasses. """ @@ -258,14 +283,15 @@ def _getcustomclass(self, name): cls = getattr(self, name) if cls != getattr(pytest, name): - py.log._apiwarn("2.0", "use of node.%s is deprecated, " + py.log._apiwarn( + "2.0", "use of node.%s is deprecated, " "use pytest_pycollect_makeitem(...) to create custom " "collection nodes" % name) 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 @@ -392,13 +418,14 @@ return excinfo.value.formatrepr() tbfilter = True if self.config.option.fulltrace: - style="long" + style = "long" else: self._prunetraceback(excinfo) tbfilter = False # prunetraceback already does it if style == "auto": style = "long" - # XXX should excinfo.getrepr record all data and toterminal() process it? + # XXX should excinfo.getrepr record all data + # and toterminal() process it? if style is None: if self.config.option.tbstyle == "short": style = "short" @@ -411,6 +438,7 @@ repr_failure = _repr_failure_py + class Collector(Node): """ Collector instances create children through collect() and thus iteratively build a tree. @@ -444,9 +472,10 @@ 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) @@ -464,9 +493,11 @@ 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. @@ -501,13 +532,15 @@ self._location = location return location + class NoMatch(Exception): """ raised if matching cannot locate a matching names. """ + class Session(FSCollector): class Interrupted(KeyboardInterrupt): """ signals an interrupted test run. """ - __module__ = 'builtins' # for py3 + __module__ = 'builtins' # for py3 def __init__(self, config): FSCollector.__init__(self, py.path.local(), parent=None, @@ -547,8 +580,8 @@ hook = self.config.hook try: items = self._perform_collect(args, genitems) - hook.pytest_collection_modifyitems(session=self, - config=self.config, items=items) + hook.pytest_collection_modifyitems( + session=self, config=self.config, items=items) finally: hook.pytest_collection_finish(session=self) return items @@ -574,7 +607,7 @@ for arg, exc in self._notfound: line = "(no name %r in any of %r)" % (arg, exc.args[0]) errors.append("not found: %s\n%s" % (arg, line)) - #XXX: test this + # XXX: test this raise pytest.UsageError(*errors) if not genitems: return rep.result @@ -603,7 +636,7 @@ names = self._parsearg(arg) path = names.pop(0) if path.check(dir=1): - assert not names, "invalid arg %r" %(arg,) + assert not names, "invalid arg %r" % (arg,) for path in path.visit(fil=lambda x: x.check(file=1), rec=self._recurse, bf=True, sort=True): for x in self._collectfile(path): @@ -724,5 +757,3 @@ for x in self.genitems(subnode): yield x node.ihook.pytest_collectreport(report=rep) - - diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/mark.py --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -192,10 +192,12 @@ if name not in self._markers: raise AttributeError("%r not a registered marker" % (name,)) + def istestfunc(func): return hasattr(func, "__call__") and \ getattr(func, "__name__", "") != "" + class MarkDecorator: """ A decorator for test functions and test classes. When applied it will create :class:`MarkInfo` objects which may be @@ -236,7 +238,8 @@ @property def markname(self): - return self.name # for backward-compat (2.4.1 had this attr) + # for backward-compat (2.4.1 had this attr) + return self.name def __repr__(self): d = self.__dict__.copy() diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/monkeypatch.py --- a/_pytest/monkeypatch.py +++ b/_pytest/monkeypatch.py @@ -1,8 +1,10 @@ """ monkeypatching and mocking functionality. """ -import os, sys +import os +import sys from py.builtin import _basestring + def pytest_funcarg__monkeypatch(request): """The returned ``monkeypatch`` funcarg provides these helper methods to modify objects, dictionaries or os.environ:: @@ -26,7 +28,6 @@ return mpatch - def derive_importpath(import_path): import pytest if not isinstance(import_path, _basestring) or "." not in import_path: @@ -58,13 +59,13 @@ return attr, obj - class Notset: def __repr__(self): return "" notset = Notset() + class monkeypatch: """ Object keeping a record of setattr/item/env/syspath changes. """ def __init__(self): @@ -91,15 +92,16 @@ if value is notset: if not isinstance(target, _basestring): - raise TypeError("use setattr(target, name, value) or " - "setattr(target, value) with target being a dotted " - "import string") + raise TypeError( + "use setattr(target, name, value) or " + "setattr(target, value) with target being a dotted " + "import string") value = name name, target = derive_importpath(target) oldval = getattr(target, name, notset) if raising and oldval is notset: - raise AttributeError("%r has no attribute %r" %(target, name)) + raise AttributeError("%r has no attribute %r" % (target, name)) # avoid class descriptors like staticmethod/classmethod if inspect.isclass(target): @@ -202,7 +204,8 @@ try: del dictionary[name] except KeyError: - pass # was already deleted, so we have the desired state + # was already deleted, so we have the desired state + pass else: dictionary[name] = value self._setitem[:] = [] diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/nose.py --- a/_pytest/nose.py +++ b/_pytest/nose.py @@ -19,8 +19,8 @@ def pytest_runtest_makereport(item, call): if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()): # let's substitute the excinfo with a pytest.skip one - call2 = call.__class__(lambda: - pytest.skip(str(call.excinfo.value)), call.when) + call2 = call.__class__( + lambda: pytest.skip(str(call.excinfo.value)), call.when) call.excinfo = call2.excinfo @@ -37,14 +37,16 @@ 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 - item.session._setupstate.addfinalizer((lambda: teardown_nose(item)), item) + # 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 diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/pastebin.py --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -1,16 +1,19 @@ """ submit failure or test session information to a pastebin service. """ import pytest -import py, sys +import py +import sys import tempfile def pytest_addoption(parser): group = parser.getgroup("terminal reporting") - group._addoption('--pastebin', metavar="mode", + group._addoption( + '--pastebin', metavar="mode", action='store', dest="pastebin", default=None, choices=['failed', 'all'], help="send failed|all info to bpaste.net pastebin service.") + @pytest.mark.trylast def pytest_configure(config): if config.option.pastebin == "all": @@ -21,11 +24,13 @@ if tr is not None: config._pastebinfile = tempfile.TemporaryFile('w+') oldwrite = tr._tw.write + def tee_write(s, **kwargs): oldwrite(s, **kwargs) config._pastebinfile.write(str(s)) tr._tw.write = tee_write + def pytest_unconfigure(config): if hasattr(config, '_pastebinfile'): # get terminal contents and delete file @@ -41,6 +46,7 @@ pastebinurl = create_new_paste(sessionlog) tr.write_line("pastebin session-log: %s\n" % pastebinurl) + def create_new_paste(contents): """ Creates a new paste using bpaste.net service. @@ -68,6 +74,7 @@ else: return 'bad response: ' + response + def pytest_terminal_summary(terminalreporter): if terminalreporter.config.option.pastebin != "failed": return @@ -84,4 +91,4 @@ 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)) diff -r 702eec88814bac62c7a852f0b0ba3fac6cb5e98e -r c5689ba15d60a456526d8f4223bd575f6fc32046 _pytest/pdb.py --- a/_pytest/pdb.py +++ b/_pytest/pdb.py @@ -9,24 +9,28 @@ def pytest_addoption(parser): group = parser.getgroup("general") - group._addoption('--pdb', - action="store_true", dest="usepdb", default=False, - help="start the interactive Python debugger on errors.") + group._addoption( + '--pdb', action="store_true", dest="usepdb", default=False, + help="start the interactive Python debugger on errors.") + def pytest_namespace(): return {'set_trace': pytestPDB().set_trace} + def pytest_configure(config): if config.getvalue("usepdb"): config.pluginmanager.register(PdbInvoke(), 'pdbinvoke') old = (pdb.set_trace, pytestPDB._pluginmanager) + def fin(): pdb.set_trace, pytestPDB._pluginmanager = old pdb.set_trace = pytest.set_trace pytestPDB._pluginmanager = config.pluginmanager config._cleanup.append(fin) + class pytestPDB: """ Pseudo PDB that defers to the real pdb. """ _pluginmanager = None @@ -55,7 +59,7 @@ def pytest_internalerror(self, excrepr, excinfo): for line in str(excrepr).split("\n"): - sys.stderr.write("INTERNALERROR> %s\n" %line) + sys.stderr.write("INTERNALERROR> %s\n" % line) sys.stderr.flush() tb = _postmortem_traceback(excinfo) post_mortem(tb) This diff is so big that we needed to truncate the remainder. Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 16:50:17 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 15:50:17 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 381 Message-ID: <20150222155017.109585.64903@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/381 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3860:c5689ba15d60 Author : Ronny Pfannschmidt Branch : flake8-clean Message: finish flake8 clean of _pytest -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sun Feb 22 17:04:41 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 16:04:41 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: flake8 clean testing/python Message-ID: <20150222160441.13924.90422@app01.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/7a1d32a342c0/ Changeset: 7a1d32a342c0 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 16:04:31+00:00 Summary: flake8 clean testing/python Affected #: 5 files diff -r c5689ba15d60a456526d8f4223bd575f6fc32046 -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 testing/python/collect.py --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1,4 +1,6 @@ -import pytest, py +import pytest +import py + class TestModule: def test_failing_import(self, testdir): @@ -32,6 +34,7 @@ modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',") pytest.raises(ImportError, lambda: modcol.obj) + class TestClass: def test_class_with_init_warning(self, testdir): testdir.makepyfile(""" @@ -292,15 +295,19 @@ config = testdir.parseconfigure() session = testdir.Session(config) session._fixturemanager = FixtureManager(session) + def func1(): pass + def func2(): pass - f1 = pytest.Function(name="name", parent=session, config=config, - args=(1,), callobj=func1) + f1 = pytest.Function( + name="name", parent=session, config=config, + 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): @@ -354,9 +361,9 @@ 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.""" + """Test parametrization with non-hashable values + with indirect parametrization.""" testdir.makepyfile(""" archival_mapping = { '1.0': {'tag': '1.0'}, @@ -382,9 +389,9 @@ 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.""" + """Test parametrization when parameter + overrides existing fixture with same name.""" testdir.makepyfile(""" import pytest @@ -400,7 +407,6 @@ rec = testdir.inline_run() rec.assertoutcome(passed=1) - def test_parametrize_with_mark(selfself, testdir): items = testdir.getitems(""" import pytest @@ -413,8 +419,12 @@ pass """) keywords = [item.keywords for item in items] - assert 'foo' in keywords[0] and 'bar' not in keywords[0] and 'baz' not in keywords[0] - assert 'foo' in keywords[1] and 'bar' in keywords[1] and 'baz' in keywords[1] + assert 'foo' in keywords[0] and \ + 'bar' not in keywords[0] and \ + 'baz' not in keywords[0] + assert 'foo' in keywords[1] and \ + 'bar' in keywords[1] and \ + 'baz' in keywords[1] def test_function_equality_with_callspec(self, testdir, tmpdir): items = testdir.getitems(""" @@ -429,9 +439,11 @@ def test_pyfunc_call(self, testdir): item = testdir.getitem("def test_func(): raise ValueError") config = item.config + class MyPlugin1: def pytest_pyfunc_call(self, pyfuncitem): raise ValueError + class MyPlugin2: def pytest_pyfunc_call(self, pyfuncitem): return True @@ -439,6 +451,7 @@ config.pluginmanager.register(MyPlugin2()) config.hook.pytest_pyfunc_call(pyfuncitem=item) + class TestSorting: def test_check_equality(self, testdir): modcol = testdir.getmodulecol(""" @@ -461,11 +474,11 @@ 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): @@ -565,11 +578,13 @@ def test_makeitem_non_underscore(self, testdir, monkeypatch): modcol = testdir.getmodulecol("def _hello(): pass") l = [] - monkeypatch.setattr(pytest.Module, 'makeitem', + monkeypatch.setattr( + pytest.Module, 'makeitem', lambda self, name, obj: l.append(name)) l = modcol.collect() assert '_hello' not in l + def test_setup_only_available_in_subdir(testdir): sub1 = testdir.mkpydir("sub1") sub2 = testdir.mkpydir("sub2") @@ -598,6 +613,7 @@ "*2 passed*" ]) + def test_modulecol_roundtrip(testdir): modcol = testdir.getmodulecol("pass", withinit=True) trail = modcol.nodeid @@ -622,13 +638,13 @@ out = result.stdout.str() assert out.find("xyz") != -1 assert out.find("conftest.py:2: ValueError") != -1 - 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 out.find("conftest.py:2: ValueError") != -1 - 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): @@ -656,6 +672,7 @@ "E*NameError*", ]) + class TestReportInfo: def test_itemreport_reportinfo(self, testdir, linecomp): testdir.makeconftest(""" @@ -792,6 +809,7 @@ "*1 passed*", ]) + def test_customize_through_attributes(testdir): testdir.makeconftest(""" import pytest diff -r c5689ba15d60a456526d8f4223bd575f6fc32046 -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 testing/python/fixture.py --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -1,25 +1,38 @@ -import pytest, py, sys +import pytest +import py +import sys from _pytest import python as funcargs from _pytest.python import FixtureLookupError from _pytest.pytester import get_public_names from textwrap import dedent + def test_getfuncargnames(): - def f(): pass + + def f(): + pass assert not funcargs.getfuncargnames(f) - def g(arg): pass + + def g(arg): + pass assert funcargs.getfuncargnames(g) == ('arg',) - def h(arg1, arg2="hello"): pass + + def h(arg1, arg2="hello"): + pass assert funcargs.getfuncargnames(h) == ('arg1',) - def h(arg1, arg2, arg3="hello"): pass + + def h(arg1, arg2, arg3="hello"): + pass assert funcargs.getfuncargnames(h) == ('arg1', 'arg2') + class A: def f(self, arg1, arg2="hello"): pass assert funcargs.getfuncargnames(A().f) == ('arg1',) - if sys.version_info < (3,0): + if sys.version_info < (3, 0): assert funcargs.getfuncargnames(A.f) == ('arg1',) + class TestFillFixtures: def test_fillfuncargs_exposed(self): # used by oejskit, kept for compatibility @@ -33,7 +46,7 @@ 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)*", @@ -361,7 +374,7 @@ assert item.funcargs["something"] == 1 assert len(get_public_names(item.funcargs)) == 2 assert "request" in item.funcargs - #assert item.funcargs == {'something': 1, "other": 2} + # assert item.funcargs == {'something': 1, "other": 2} def test_request_addfinalizer(self, testdir): item = testdir.getitem(""" @@ -412,7 +425,6 @@ 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(""" l = [] @@ -426,7 +438,7 @@ result = testdir.runpytest(p) result.stdout.fnmatch_lines([ "*1 error*" # XXX the whole module collection fails - ]) + ]) def test_request_getmodulepath(self, testdir): modcol = testdir.getmodulecol("def test_somefunc(): pass") @@ -543,9 +555,10 @@ reprec = testdir.inline_run() reprec.assertoutcome(passed=2) + class TestRequestMarking: def test_applymarker(self, testdir): - item1,item2 = testdir.getitems(""" + item1, item2 = testdir.getitems(""" def pytest_funcarg__something(request): pass class TestClass: @@ -600,6 +613,7 @@ reprec = testdir.inline_run() reprec.assertoutcome(passed=2) + class TestRequestCachedSetup: def test_request_cachedsetup_defaultmodule(self, testdir): reprec = testdir.inline_runsource(""" @@ -638,6 +652,7 @@ item1 = testdir.getitem("def test_func(): pass") req1 = funcargs.FixtureRequest(item1) l = ["hello", "world"] + def setup(): return l.pop() ret1 = req1.cached_setup(setup, extrakey=1) @@ -653,8 +668,10 @@ item1 = testdir.getitem("def test_func(): pass") req1 = funcargs.FixtureRequest(item1) l = [] + def setup(): l.append("setup") + def teardown(val): l.append("teardown") req1.cached_setup(setup, teardown, scope="function") @@ -742,6 +759,7 @@ "*ZeroDivisionError*", ]) + class TestFixtureUsages: def test_noargfixturedec(self, testdir): testdir.makepyfile(""" @@ -962,7 +980,7 @@ 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: @@ -1248,8 +1266,6 @@ reprec = testdir.inline_run() reprec.assertoutcome(passed=2) - - def test_funcarg_and_setup(self, testdir): testdir.makepyfile(""" import pytest @@ -1355,7 +1371,7 @@ def test_2(self): pass """) - reprec = testdir.inline_run("-v","-s") + reprec = testdir.inline_run("-v", "-s") reprec.assertoutcome(passed=8) config = reprec.getcalls("pytest_unconfigure")[0].config l = config._conftest.getconftestmodules(p)[0].l @@ -1393,7 +1409,8 @@ @pytest.fixture(scope="class", autouse=True) def addteardown(self, item, request): l.append("setup-%d" % item) - request.addfinalizer(lambda: l.append("teardown-%d" % item)) + request.addfinalizer( + lambda: l.append("teardown-%d" % item)) def test_step1(self, item): l.append("step1-%d" % item) def test_step2(self, item): @@ -1425,9 +1442,10 @@ 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"]) - def test_ordering_dependencies_torndown_first(self, testdir, param1, param2): + @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 l = [] @@ -1719,7 +1737,7 @@ 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(""" @@ -1854,7 +1872,7 @@ '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 @@ -1962,7 +1980,7 @@ """) 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(""" @@ -1984,7 +2002,7 @@ 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 @@ -2012,7 +2030,6 @@ 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): @@ -2054,7 +2071,8 @@ l = [] @pytest.fixture(params=["John", "Doe"], scope="class") def human(request): - request.addfinalizer(lambda: l.append("fin %s" % request.param)) + request.addfinalizer( + lambda: l.append("fin %s" % request.param)) return request.param class TestGreetings: @@ -2155,7 +2173,7 @@ class TestRequestScopeAccess: - 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"], @@ -2176,7 +2194,7 @@ 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) @@ -2194,10 +2212,11 @@ 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: def test_subfactory_missing_funcarg(self, testdir): testdir.makepyfile(""" @@ -2243,8 +2262,6 @@ *3 pass*2 error* """) - - def test_setupfunc_missing_funcarg(self, testdir): testdir.makepyfile(""" import pytest @@ -2262,6 +2279,7 @@ "*1 error*", ]) + class TestShowFixtures: def test_funcarg_compat(self, testdir): config = testdir.parseconfigure("--funcargs") @@ -2270,18 +2288,16 @@ 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(''' @@ -2324,7 +2340,6 @@ """) - class TestContextManagerFixtureFuncs: def test_simple(self, testdir): testdir.makepyfile(""" @@ -2419,7 +2434,6 @@ *test_yields*:2* """) - def test_no_yield(self, testdir): testdir.makepyfile(""" import pytest @@ -2450,4 +2464,3 @@ *fixture*cannot use*yield* *def arg1* """) - diff -r c5689ba15d60a456526d8f4223bd575f6fc32046 -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 testing/python/integration.py --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -2,8 +2,9 @@ from _pytest import runner from _pytest import python + class TestOEJSKITSpecials: - 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): @@ -27,7 +28,7 @@ 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): @@ -59,10 +60,12 @@ def test_wrapped_getfslineno(): def func(): pass + def wrap(f): func.__wrapped__ = f func.patchings = ["qwe"] return func + @wrap def wrapped_func(x, y, z): pass @@ -70,14 +73,17 @@ fs2, lineno2 = python.getfslineno(wrap) assert lineno > lineno2, "getfslineno does not unwrap correctly" + class TestMockDecoration: def test_wrapped_getfuncargnames(self): from _pytest.python import getfuncargnames + def wrap(f): def func(): pass func.__wrapped__ = f return func + @wrap def f(x): pass @@ -86,12 +92,14 @@ def test_wrapped_getfuncargnames_patching(self): from _pytest.python import getfuncargnames + def wrap(f): def func(): pass func.__wrapped__ = f func.patchings = ["qwe"] return func + @wrap def f(x, y, z): pass @@ -159,7 +167,7 @@ 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): @@ -232,6 +240,7 @@ *2 passed* """) + def test_pytestconfig_is_session_scoped(): from _pytest.python import pytestconfig assert pytestconfig._pytestfixturefunction.scope == "session" @@ -248,7 +257,7 @@ assert not reprec.getfailedcollections() calls = reprec.getreports("pytest_runtest_logreport") assert not calls - + def test_class_and_method(self, testdir): testdir.makepyfile(""" __test__ = True diff -r c5689ba15d60a456526d8f4223bd575f6fc32046 -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 testing/python/metafunc.py --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1,6 +1,7 @@ +import py +import pytest +from _pytest import python as funcargs -import pytest, py -from _pytest import python as funcargs class TestMetafunc: def Metafunc(self, func): @@ -9,6 +10,7 @@ # initiliazation class FixtureInfo: name2fixturedefs = None + def __init__(self, names): self.names_closure = names names = funcargs.getfuncargnames(func) @@ -16,13 +18,15 @@ return funcargs.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 @@ -30,7 +34,8 @@ 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 @@ -39,7 +44,8 @@ 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)") @@ -52,9 +58,12 @@ 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: pass + + class obj: + pass metafunc.addcall(param=obj) metafunc.addcall(param=obj) metafunc.addcall(param=1) @@ -64,9 +73,12 @@ 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: pass + + class obj: + pass metafunc.addcall(funcargs={"x": 2}) metafunc.addcall(funcargs={"x": 3}) pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})") @@ -76,38 +88,44 @@ 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_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"] + assert ids == ["basic-abc", "basic-def", + "advanced-abc", "advanced-def"] 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'])) + with pytest.raises(ValueError): + metafunc.parametrize("x", [1, 2], ids=['basic']) - pytest.raises(ValueError, lambda: - metafunc.parametrize(("x","y"), [("abc", "def"), - ("ghi", "jkl")], ids=["one"])) + with pytest.raises(ValueError): + metafunc.parametrize(("x", "y"), [("abc", "def"), + ("ghi", "jkl")], ids=["one"]) def test_parametrize_with_userobjects(self): - def func(x, y): pass + def func(x, y): + pass metafunc = self.Metafunc(func) + class A: pass metafunc.parametrize("x", [A(), A()]) @@ -133,14 +151,15 @@ def test_idmaker_native_strings(self): from _pytest.python import idmaker - result = idmaker(("a", "b"), [(1.0, -1.1), - (2, -202), - ("three", "three hundred"), - (True, False), - (None, None), - (list("six"), [66, 66]), - (set([7]), set("seven")), - (tuple("eight"), (8, -8, 8)) + result = idmaker(("a", "b"), [ + (1.0, -1.1), + (2, -202), + ("three", "three hundred"), + (True, False), + (None, None), + (list("six"), [66, 66]), + (set([7]), set("seven")), + (tuple("eight"), (8, -8, 8)), ]) assert result == ["1.0--1.1", "2--202", @@ -154,54 +173,54 @@ @pytest.mark.issue351 def test_idmaker_idfn(self): from _pytest.python import idmaker + def ids(val): if isinstance(val, Exception): return repr(val) - result = idmaker(("a", "b"), [(10.0, IndexError()), - (20, KeyError()), - ("three", [1, 2, 3]), + result = idmaker(("a", "b"), [ + (10.0, IndexError()), + (20, KeyError()), + ("three", [1, 2, 3]), ], idfn=ids) assert result == ["10.0-IndexError()", "20-KeyError()", - "three-b2", - ] + "three-b2"] @pytest.mark.issue351 def test_idmaker_idfn_unique_names(self): from _pytest.python import idmaker + def ids(val): return 'a' - result = idmaker(("a", "b"), [(10.0, IndexError()), - (20, KeyError()), - ("three", [1, 2, 3]), + result = idmaker(("a", "b"), [ + (10.0, IndexError()), + (20, KeyError()), + ("three", [1, 2, 3]), ], idfn=ids) - assert result == ["0a-a", - "1a-a", - "2a-a", - ] + assert result == ["0a-a", "1a-a", "2a-a"] @pytest.mark.issue351 def test_idmaker_idfn_exception(self): from _pytest.python import idmaker + def ids(val): raise Exception("bad code") - result = idmaker(("a", "b"), [(10.0, IndexError()), - (20, KeyError()), - ("three", [1, 2, 3]), + result = idmaker(("a", "b"), [ + (10.0, IndexError()), + (20, KeyError()), + ("three", [1, 2, 3]), ], idfn=ids) - assert result == ["10.0-b0", - "20-b1", - "three-b2", - ] + assert result == ["10.0-b0", "20-b1", "three-b2"] 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} @@ -209,28 +228,30 @@ assert metafunc._calls[1].id == "0-3" 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) metafunc.parametrize('unnamed', [1], 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, unnamed=1) - assert metafunc._calls[1].params == dict(x=1,y=3, unnamed=1) + assert metafunc._calls[0].params == dict(x=1, y=2, unnamed=1) + assert metafunc._calls[1].params == dict(x=1, y=3, unnamed=1) 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(""" @@ -255,7 +276,7 @@ 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" @@ -264,15 +285,15 @@ 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" @@ -317,7 +338,8 @@ items = scenario[1].items() argnames = [x[0] for x in items] argvalues.append(([x[1] for x in items])) - metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class") + metafunc.parametrize( + argnames, argvalues, ids=idlist, scope="class") class Test(object): scenarios = [['1', {'arg': {1: 2}, "arg2": "value2"}], @@ -344,6 +366,7 @@ *6 passed* """) + class TestMetafuncFunctional: def test_attributes(self, testdir): p = testdir.makepyfile(""" @@ -436,7 +459,6 @@ "*1 pass*", ]) - def test_generate_plugin_and_module(self, testdir): testdir.makeconftest(""" def pytest_generate_tests(metafunc): @@ -695,6 +717,7 @@ class TestMarkersWithParametrization: pytestmark = pytest.mark.issue308 + def test_simple_mark(self, testdir): s = """ import pytest @@ -843,7 +866,8 @@ @pytest.mark.parametrize(("n", "expected"), [ (1, 2), - pytest.mark.xfail("sys.version > 0", reason="some bug")((2, 3)), + pytest.mark.xfail( + "sys.version > 0", reason="some bug")((2, 3)), (3, 4), ]) def test_increment(n, expected): @@ -877,7 +901,6 @@ 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(""" diff -r c5689ba15d60a456526d8f4223bd575f6fc32046 -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 testing/python/raises.py --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -1,5 +1,6 @@ import pytest + class TestRaises: def test_raises(self): source = "int('qwe')" @@ -29,10 +30,9 @@ def test_raises_flip_builtin_AssertionError(self): # we replace AssertionError on python level # however c code might still raise the builtin one - from _pytest.assertion.util import BuiltinAssertionError # noqa - pytest.raises(AssertionError,""" - raise BuiltinAssertionError - """) + from _pytest.assertion.util import BuiltinAssertionError + with pytest.raises(AssertionError): + raise BuiltinAssertionError() @pytest.mark.skipif('sys.version < "2.5"') def test_raises_as_contextmanager(self, testdir): Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 17:12:10 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 16:12:10 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 382 Message-ID: <20150222161210.10164.6456@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/382 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3861:7a1d32a342c0 Author : Ronny Pfannschmidt Branch : flake8-clean Message: flake8 clean testing/python -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sun Feb 22 19:07:40 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 18:07:40 -0000 Subject: [Pytest-commit] commit/pytest: 3 new changesets Message-ID: <20150222180740.5054.3789@app06.ash-private.bitbucket.org> 3 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/eb3382c1cf50/ Changeset: eb3382c1cf50 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 16:10:00+00:00 Summary: flake8 clean testing/cx_freeze Affected #: 4 files diff -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 -r eb3382c1cf5061a70396445727c1ca8102be95f3 testing/cx_freeze/runtests_script.py --- a/testing/cx_freeze/runtests_script.py +++ b/testing/cx_freeze/runtests_script.py @@ -6,4 +6,4 @@ if __name__ == '__main__': import sys import pytest - sys.exit(pytest.main()) \ No newline at end of file + sys.exit(pytest.main()) diff -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 -r eb3382c1cf5061a70396445727c1ca8102be95f3 testing/cx_freeze/runtests_setup.py --- a/testing/cx_freeze/runtests_setup.py +++ b/testing/cx_freeze/runtests_setup.py @@ -1,5 +1,6 @@ """ -Sample setup.py script that generates an executable with pytest runner embedded. +Sample setup.py script that generates an executable +with pytest runner embedded. """ if __name__ == '__main__': from cx_Freeze import setup, Executable @@ -8,8 +9,8 @@ setup( name="runtests", version="0.1", - description="exemple of how embedding py.test into an executable using cx_freeze", + description="exemple of how embedding py.test " + "into an executable using cx_freeze", executables=[Executable("runtests_script.py")], options={"build_exe": {'includes': pytest.freeze_includes()}}, ) - diff -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 -r eb3382c1cf5061a70396445727c1ca8102be95f3 testing/cx_freeze/tests/test_trivial.py --- a/testing/cx_freeze/tests/test_trivial.py +++ b/testing/cx_freeze/tests/test_trivial.py @@ -2,5 +2,6 @@ def test_upper(): assert 'foo'.upper() == 'FOO' + def test_lower(): - assert 'FOO'.lower() == 'foo' \ No newline at end of file + assert 'FOO'.lower() == 'foo' diff -r 7a1d32a342c0433d9c30889fa04d59fbd11d3557 -r eb3382c1cf5061a70396445727c1ca8102be95f3 testing/cx_freeze/tox_run.py --- a/testing/cx_freeze/tox_run.py +++ b/testing/cx_freeze/tox_run.py @@ -12,4 +12,4 @@ executable = os.path.join(os.getcwd(), 'build', 'runtests_script') if sys.platform.startswith('win'): executable += '.exe' - sys.exit(os.system('%s tests' % executable)) \ No newline at end of file + sys.exit(os.system('%s tests' % executable)) https://bitbucket.org/hpk42/pytest/commits/60e93163ce6f/ Changeset: 60e93163ce6f Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 18:01:22+00:00 Summary: flake8 clean testing Affected #: 31 files diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/acceptance_test.py --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1,4 +1,6 @@ -import py, pytest +import py +import pytest + class TestGeneralUsage: def test_config_error(self, testdir): @@ -65,14 +67,13 @@ 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): @@ -110,7 +111,7 @@ 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", "E ImportError: No module named *does_not_work*", ]) assert result.ret == 1 @@ -121,7 +122,7 @@ 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): @@ -137,7 +138,6 @@ *ERROR*could not load*conftest.py* """) - def test_early_skip(self, testdir): testdir.mkdir("xyz") testdir.makeconftest(""" @@ -245,7 +245,7 @@ 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*", @@ -300,7 +300,7 @@ 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*", @@ -308,7 +308,8 @@ assert 'sessionstarttime' not in result.stderr.str() @pytest.mark.parametrize('lookfor', ['test_fun.py', 'test_fun.py::test_a']) - def test_issue134_report_syntaxerror_when_collecting_member(self, testdir, lookfor): + def test_issue134_report_syntaxerror_when_collecting_member( + self, testdir, lookfor): testdir.makepyfile(test_fun=""" def test_a(): pass @@ -546,6 +547,7 @@ "*1 failed*", ]) + class TestDurations: source = """ import time @@ -583,12 +585,12 @@ 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) @@ -621,6 +623,7 @@ def test_2(): time.sleep(frag) """ + def test_setup_function(self, testdir): testdir.makepyfile(self.source) result = testdir.runpytest("--durations=10") @@ -631,4 +634,3 @@ * setup *test_1* * call *test_1* """) - diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/conftest.py --- a/testing/conftest.py +++ b/testing/conftest.py @@ -1,9 +1,10 @@ import pytest import sys +import os +import py pytest_plugins = "pytester", -import os, py class LsofFdLeakChecker(object): def get_open_files(self): @@ -18,7 +19,10 @@ 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) + "deleted" not in line and + 'mem' not in line and + "txt" not in line and + 'cwd' not in line) open_files = [] @@ -34,9 +38,11 @@ def pytest_addoption(parser): - parser.addoption('--lsof', - action="store_true", dest="lsof", default=False, - help=("run FD checks if lsof is available")) + parser.addoption( + '--lsof', + action="store_true", dest="lsof", default=False, + help=("run FD checks if lsof is available")) + def pytest_runtest_setup(item): config = item.config @@ -48,12 +54,13 @@ except py.process.cmdexec.Error: pass -#def pytest_report_header(): + +# ef pytest_report_header(): # return "pid: %s" % os.getpid() def check_open_files(config): lines2 = config._fd_leak_checker.get_open_files() - new_fds = set([t[0] for t in lines2]) - set([t[0] for t in config._openfiles]) + new_fds = set(t[0] for t in lines2) - set(t[0] for t in config._openfiles) open_files = [t for t in lines2 if t[0] in new_fds] if open_files: error = [] @@ -66,6 +73,7 @@ error.append(error[0]) raise AssertionError("\n".join(error)) + def pytest_runtest_teardown(item, __multicall__): item.config._basedir.chdir() if hasattr(item.config, '_openfiles'): @@ -84,6 +92,7 @@ 'python3.5': r'C:\Python35\python.exe', } + def getexecutable(name, cache={}): try: return cache[name] @@ -92,16 +101,18 @@ if executable: if name == "jython": import subprocess - popen = subprocess.Popen([str(executable), "--version"], + popen = subprocess.Popen( + [str(executable), "--version"], universal_newlines=True, stderr=subprocess.PIPE) out, err = popen.communicate() 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 cache[name] = executable return executable + @pytest.fixture(params=['python2.6', 'python2.7', 'python3.3', "python3.4", 'pypy', 'pypy3']) def anypython(request): diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_argcomplete.py --- a/testing/test_argcomplete.py +++ b/testing/test_argcomplete.py @@ -1,8 +1,10 @@ from __future__ import with_statement -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)) @@ -14,15 +16,18 @@ out.write(' bash - python: %s\n' % (res_bash - set(res))) return retval + # 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.') + raise ValueError( + 'stdout argument not allowed, it will be overridden.') process = py.std.subprocess.Popen( stdout=py.std.subprocess.PIPE, *args, **kargs) output, unused_err = process.communicate() @@ -36,9 +41,11 @@ 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 +57,31 @@ 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)]) + completion += _wrapcall( + ['bash', '-c', + "compgen -A file -X '!*.{0}' -- '{p}'".format( + x, p=prefix)]) else: - completion += _wrapcall(['bash', '-c', - "compgen -A file -- '{p}'".format(p=prefix)]) + completion += _wrapcall( + ['bash', '-c', + "compgen -A file -- '{p}'".format(p=prefix)]) - anticomp = _wrapcall(['bash', '-c', - "compgen -A directory -- '{p}'".format(p=prefix)]) + anticomp = _wrapcall( + ['bash', '-c', + "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 + # the following barfs with a syntax error on py2.5 # @pytest.mark.skipif("sys.version_info < (2,6)") class TestArgComplete: diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_assertion.py --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -2,7 +2,8 @@ import sys import textwrap -import py, pytest +import py +import pytest import _pytest.assertion as plugin from _pytest.assertion import reinterpret from _pytest.assertion import util @@ -15,6 +16,7 @@ def mock_config(): class Config(object): verbose = False + def getoption(self, name): if name == 'verbose': return self.verbose @@ -25,6 +27,7 @@ def interpret(expr): return reinterpret.reinterpret(expr, py.code.Frame(sys._getframe(1))) + class TestBinReprIntegration: pytestmark = needsnewassert @@ -48,6 +51,7 @@ "*test_check*PASS*", ]) + def callequal(left, right, verbose=False): config = mock_config() config.verbose = verbose @@ -68,15 +72,15 @@ 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' @@ -123,7 +127,8 @@ def test_iterable_full_diff(self, left, right, expected): """Test the full diff assertion failure explanation. - When verbose is False, then just a -v notice to get the diff is rendered, + When verbose is False, + then just a -v notice to get the diff is rendered, when verbose is True, then ndiff of the pprint is returned. """ expl = callequal(left, right, verbose=False) @@ -194,9 +199,9 @@ 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): @@ -350,6 +355,7 @@ *1 failed* """) + @needsnewassert def test_rewritten(testdir): testdir.makepyfile(""" @@ -358,11 +364,13 @@ """) 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', '? +++'] + @needsnewassert def test_pytest_assertrepr_compare_integration(testdir): testdir.makepyfile(""" @@ -380,6 +388,7 @@ "*E*50*", ]) + @needsnewassert def test_sequence_comparison_uses_repr(testdir): testdir.makepyfile(""" @@ -415,7 +424,6 @@ "*truncated*use*-vv*", ]) - result = testdir.runpytest('-vv') result.stdout.fnmatch_lines([ "*- 197", @@ -437,12 +445,12 @@ 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): @@ -464,6 +472,7 @@ result = testdir.runpytest(*opt) assert "3 == 4" not in result.stdout.str() + def test_old_assert_mode(testdir): testdir.makepyfile(""" def test_in_old_mode(): @@ -472,6 +481,7 @@ result = testdir.runpytest("--assert=reinterp") assert result.ret == 0 + def test_triple_quoted_string_issue113(testdir): testdir.makepyfile(""" def test_hello(): @@ -483,6 +493,7 @@ ]) assert 'SyntaxError' not in result.stdout.str() + def test_traceback_failure(testdir): p1 = testdir.makepyfile(""" def g(): @@ -503,7 +514,7 @@ "", "*test_*.py:6: ", "_ _ _ *", - #"", + # "", " def f(x):", "> assert x == g()", "E assert 3 == 2", @@ -512,7 +523,7 @@ "*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 *====", @@ -531,7 +542,11 @@ "*test_traceback_failure.py:4: AssertionError" ]) - at pytest.mark.skipif("sys.version_info < (2,5) or '__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')" ) + + at pytest.mark.skipif( + "sys.version_info < (2,5) or " + "'__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") @@ -543,6 +558,7 @@ "*WARNING*assert statements are not executed*", ]) + def test_recursion_source_decode(testdir): testdir.makepyfile(""" def test_something(): @@ -557,15 +573,16 @@ """) + def test_AssertionError_message(testdir): testdir.makepyfile(""" def test_hello(): x,y = 1,2 - assert 0, (x,y) + assert 0, (x, y) """) result = testdir.runpytest() result.stdout.fnmatch_lines(""" *def test_hello* - *assert 0, (x,y)* + *assert 0, (x, y)* *AssertionError: (1, 2)* """) diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_assertrewrite.py --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -4,20 +4,20 @@ 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 ast from _pytest.assertion import util from _pytest.assertion.rewrite import rewrite_asserts, PYTEST_TAG def setup_module(mod): + if sys.platform.startswith("java"): + # XXX should be xfail + pytest.skip("assert rewrite does currently not work on jython") + mod._old_reprcompare = util._reprcompare py.code._reprcompare = None + def teardown_module(mod): util._reprcompare = mod._old_reprcompare del mod._old_reprcompare @@ -28,6 +28,7 @@ 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(py.code.Code(f).source().lines) @@ -102,21 +103,28 @@ def f(): assert False assert getmsg(f) == "assert False" + def f(): f = False assert f assert getmsg(f) == "assert False" + 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 + 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(): @@ -189,45 +197,57 @@ f = g = False assert f and g assert getmsg(f) == "assert (False)" + def f(): f = True g = False assert f and g assert getmsg(f) == "assert (True and False)" + def f(): f = False g = True assert f and g assert getmsg(f) == "assert (False)" + def f(): f = g = False assert f or g assert getmsg(f) == "assert (False or False)" + def f(): f = g = False assert not f and not g getmsg(f, must_pass=True) + def x(): return False + def f(): assert x() and x() - assert getmsg(f, {"x" : x}) == "assert (x())" + + assert getmsg(f, {"x": x}) == "assert (x())" + def f(): assert False or x() - assert getmsg(f, {"x" : x}) == "assert (False or x())" + assert getmsg(f, {"x": x}) == "assert (False or x())" + def f(): assert 1 in {} and 2 in {} assert getmsg(f) == "assert (1 in {})" + 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 {})" + def f(): f = True g = False assert f or g getmsg(f, must_pass=True) + def f(): f = g = h = lambda: True assert f() and g() and h() @@ -237,6 +257,7 @@ def f(): assert True or explode # noqa getmsg(f, must_pass=True) + def f(): x = 1 assert x == 1 or x == 2 @@ -247,14 +268,17 @@ x = True assert not x assert getmsg(f) == "assert not True" + def f(): x = 0 assert ~x + 1 assert getmsg(f) == "assert (~0 + 1)" + def f(): x = 3 assert -x + x assert getmsg(f) == "assert (-3 + 3)" + def f(): x = 0 assert +x + x @@ -266,6 +290,7 @@ y = -1 assert x + y assert getmsg(f) == "assert (1 + -1)" + def f(): assert not 5 % 4 assert getmsg(f) == "assert not (5 % 4)" @@ -274,6 +299,7 @@ def f(): assert 3 % 2 and False assert getmsg(f) == "assert ((3 % 2) and False)" + def f(): assert False or 4 % 2 assert getmsg(f) == "assert (False or (4 % 2))" @@ -281,39 +307,48 @@ def test_call(self): def g(a=42, *args, **kwargs): return False - ns = {"g" : g} + ns = {"g": g} + def f(): assert g() assert getmsg(f, ns) == """assert g()""" + def f(): assert g(1) assert getmsg(f, ns) == """assert g(1)""" + def f(): assert g(1, 2) assert getmsg(f, ns) == """assert g(1, 2)""" + def f(): assert g(1, g=42) assert getmsg(f, ns) == """assert g(1, g=42)""" + def f(): assert g(1, 3, g=23) assert getmsg(f, ns) == """assert g(1, 3, g=23)""" + def f(): seq = [1, 2, 3] assert g(*seq) assert getmsg(f, ns) == """assert g(*[1, 2, 3])""" + def f(): x = "a" - assert g(**{x : 2}) + assert g(**{x: 2}) assert getmsg(f, ns) == """assert g(**{'a': 2})""" def test_attribute(self): 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""" + def f(): x.a = False # noqa assert x.a # noqa @@ -324,18 +359,22 @@ a, b = range(2) assert b < a assert getmsg(f) == """assert 1 < 0""" + def f(): a, b, c = range(3) assert a > b > c assert getmsg(f) == """assert 0 > 1""" + def f(): a, b, c = range(3) assert a < b > c assert getmsg(f) == """assert 1 > 2""" + def f(): a, b, c = range(3) assert a < b <= c getmsg(f, must_pass=True) + def f(): a, b, c = range(3) assert a < b @@ -353,12 +392,15 @@ def my_reprcompare(op, left, right): return "42" monkeypatch.setattr(util, "_reprcompare", my_reprcompare) + def f(): assert 42 < 3 assert getmsg(f) == "assert 42" + def my_reprcompare(op, left, right): return "%s %s %s" % (left, op, right) monkeypatch.setattr(util, "_reprcompare", my_reprcompare) + def f(): assert 1 < 3 < 5 <= 4 < 7 assert getmsg(f) == "assert 5 <= 4" @@ -368,10 +410,13 @@ class A(object): def __nonzero__(self): raise ValueError(42) + def __lt__(self, other): return A() + def __repr__(self): return "" + def myany(x): return False assert myany(A() < 0) @@ -434,7 +479,7 @@ 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") @@ -461,8 +506,8 @@ import pytest def test_optimized(): "hello" - assert test_optimized.__doc__ is None""" - ) + assert test_optimized.__doc__ is None + """) p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None, rootdir=testdir.tmpdir) tmp = "--basetemp=%s" % p @@ -486,19 +531,22 @@ assert testdir.runpytest().ret == 0 def test_translate_newlines(self, testdir): - content = "def test_rewritten():\r\n assert '@py_builtins' in globals()" + content = ("def test_rewritten():\r\n" + " assert '@py_builtins' in globals()") b = content.encode("utf-8") 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() testdir.makepyfile("import a_package_without_init_py.module") assert testdir.runpytest().ret == 0 + class TestAssertionRewriteHookDetails(object): def test_loader_is_package_false_for_module(self, testdir): testdir.makepyfile(test_fun=""" @@ -581,6 +629,7 @@ source_path = tmpdir.ensure("source.py") pycpath = tmpdir.join("pyc").strpath assert _write_pyc(state, [1], source_path.stat(), pycpath) + def open(*args): e = IOError() e.errno = 10 @@ -607,7 +656,8 @@ def test_load_resource(): assert isinstance(__loader__, AssertionRewritingHook) - res = pkg_resources.resource_string(__name__, 'resource.txt') + res = pkg_resources.resource_string( + __name__, 'resource.txt') res = res.decode('ascii') assert res == 'Load me please.' """, diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_capture.py --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -44,10 +44,10 @@ 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) @@ -66,8 +66,9 @@ assert parser._groups[0].options[0].default == "sys" @needsosdup - @pytest.mark.parametrize("method", - ['no', 'sys', pytest.mark.skipif('not hasattr(os, "dup")', 'fd')]) + @pytest.mark.parametrize("method", [ + '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 @@ -107,7 +108,7 @@ @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'" @@ -229,7 +230,7 @@ "setup func1*", "in func1*", "teardown func1*", - #"*1 fixture failure*" + # "*1 fixture failure*" ]) def test_teardown_capturing_final(self, testdir): @@ -615,6 +616,7 @@ if not f.closed: f.close() + @needsosdup def test_dupfile(tmpfile): flist = [] @@ -633,12 +635,14 @@ 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") @@ -961,6 +965,7 @@ capfile2 = cap.err.tmpfile assert capfile2 == capfile + @needsosdup def test_close_and_capture_again(testdir): testdir.makepyfile(""" @@ -980,7 +985,6 @@ """) - @pytest.mark.parametrize('method', ['SysCapture', 'FDCapture']) def test_capturing_and_logging_fundamentals(testdir, method): if method == "StdCaptureFD" and not hasattr(os, 'dup'): diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_collection.py --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1,7 +1,9 @@ -import pytest, py +import pytest +import py from _pytest.main import Session + class TestCollector: def test_collect_versus_item(self): from pytest import Collector, Item @@ -41,11 +43,11 @@ 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): @@ -67,7 +69,6 @@ parent = fn.getparent(pytest.Class) assert parent is cls - def test_getcustomfile_roundtrip(self, testdir): hello = testdir.makefile(".xxx", hello="world") testdir.makepyfile(conftest=""" @@ -85,6 +86,7 @@ assert len(nodes) == 1 assert isinstance(nodes[0], pytest.File) + class TestCollectFS: def test_ignored_certain_directories(self, testdir): tmpdir = testdir.tmpdir @@ -116,9 +118,11 @@ rec = testdir.inline_run("xyz123/test_2.py") rec.assertoutcome(failed=1) + class TestCollectPluginHookRelay: def test_pytest_collect_file(self, testdir): wascalled = [] + class Plugin: def pytest_collect_file(self, path, parent): wascalled.append(path) @@ -129,6 +133,7 @@ def test_pytest_collect_directory(self, testdir): wascalled = [] + class Plugin: def pytest_collect_directory(self, path, parent): wascalled.append(path.basename) @@ -138,6 +143,7 @@ assert "hello" in wascalled assert "world" in wascalled + class TestPrunetraceback: def test_collection_error(self, testdir): p = testdir.makepyfile(""" @@ -289,6 +295,7 @@ "*test_x*" ]) + class TestSession: def test_parsearg(self, testdir): p = testdir.makepyfile("def test_func(): pass") @@ -303,11 +310,11 @@ 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): @@ -318,14 +325,13 @@ 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 - def test_collect_protocol_single_function(self, testdir): p = testdir.makepyfile("def test_func(): pass") id = "::".join([p.basename, "test_func"]) @@ -392,7 +398,7 @@ "collector.__class__.__name__ == 'Module'"), ("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_collectreport", "report.nodeid.startswith(p.basename)"), - #("pytest_collectreport", + # ("pytest_collectreport", # "report.fspath == %r" % str(rcol.fspath)), ]) @@ -409,7 +415,7 @@ ("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): @@ -457,6 +463,7 @@ item, = items assert item.nodeid.endswith("TestClass::()::test_method") + class Test_getinitialnodes: def test_global_file(self, testdir, tmpdir): x = tmpdir.ensure("x.py") @@ -483,6 +490,7 @@ for col in col.listchain(): assert col.config is config + class Test_genitems: def test_check_collect_hashes(self, testdir): p = testdir.makepyfile(""" diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,7 +1,9 @@ -import py, pytest +import py +import pytest from _pytest.config import getcfg + class TestParseIni: def test_getcfg_and_config(self, testdir, tmpdir): sub = tmpdir.mkdir("sub") @@ -16,7 +18,7 @@ assert config.inicfg['name'] == 'value' def test_getcfg_empty_path(self, tmpdir): - getcfg([''], ['setup.cfg']) #happens on py.test "" + getcfg([''], ['setup.cfg']) # happens on py.test "" def test_append_parse_args(self, testdir, tmpdir, monkeypatch): monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"') @@ -29,10 +31,10 @@ assert config.option.reportchars == 's' assert config.option.tbstyle == 'short' assert config.option.verbose - #config = testdir.Config() - #args = [tmpdir,] - #config._preparse(args, addopts=False) - #assert len(args) == 1 + # config = testdir.Config() + # args = [tmpdir,] + # config._preparse(args, addopts=False) + # assert len(args) == 1 def test_tox_ini_wrong_version(self, testdir): testdir.makefile('.ini', tox=""" @@ -78,6 +80,7 @@ result = testdir.runpytest("--confcutdir=.") assert result.ret == 0 + class TestConfigCmdlineParsing: def test_parsing_again_fails(self, testdir): config = testdir.parseconfig() @@ -92,13 +95,14 @@ [pytest] custom = 0 """) - testdir.makefile(".cfg", custom = """ + testdir.makefile(".cfg", custom=""" [pytest] custom = 1 """) config = testdir.parseconfig("-c", "custom.cfg") assert config.getini("custom") == "1" + class TestConfigAPI: def test_config_trace(self, testdir): config = testdir.parseconfig() @@ -131,7 +135,8 @@ def test_config_getvalueorskip(self, testdir): config = testdir.parseconfig() - pytest.raises(pytest.skip.Exception, + pytest.raises( + pytest.skip.Exception, "config.getvalueorskip('hello')") verbose = config.getvalueorskip("verbose") assert verbose == config.option.verbose @@ -263,6 +268,7 @@ assert len(l) == 2 assert l == ["456", "123"] + def test_options_on_small_file_do_not_blow_up(testdir): def runfiletest(opts): reprec = testdir.inline_run(*opts) @@ -279,14 +285,19 @@ ['--traceconfig'], ['-v'], ['-v', '-v']): runfiletest(opts + [path]) + def test_preparse_ordering_with_setuptools(testdir, monkeypatch): pkg_resources = pytest.importorskip("pkg_resources") + def my_iter(name): assert name == "pytest11" + class EntryPoint: name = "mytestplugin" + class dist: pass + def load(self): class PseudoPlugin: x = 42 @@ -301,12 +312,16 @@ plugin = config.pluginmanager.getplugin("mytestplugin") assert plugin.x == 42 + def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch): pkg_resources = pytest.importorskip("pkg_resources") + def my_iter(name): assert name == "pytest11" + class EntryPoint: name = "mytestplugin" + def load(self): assert 0, "should not arrive here" return iter([EntryPoint()]) @@ -315,6 +330,7 @@ plugin = config.pluginmanager.getplugin("mytestplugin") assert plugin == -1 + def test_cmdline_processargs_simple(testdir): testdir.makeconftest(""" def pytest_cmdline_preparse(args): @@ -332,12 +348,14 @@ result = testdir.runpytest("-m", "hello" * 500) assert result.ret == 0 + def test_notify_exception(testdir, capfd): config = testdir.parseconfig() excinfo = pytest.raises(ValueError, "raise ValueError(1)") config.notify_exception(excinfo) out, err = capfd.readouterr() assert "ValueError" in err + class A: def pytest_internalerror(self, excrepr): return True @@ -348,8 +366,9 @@ def test_load_initial_conftest_last_ordering(testdir): - from _pytest.config import get_plugin_manager + from _pytest.config import get_plugin_manager pm = get_plugin_manager() + class My: def pytest_load_initial_conftests(self): pass @@ -360,6 +379,7 @@ assert l[-2] == m.pytest_load_initial_conftests assert l[-3].__module__ == "_pytest.config" + class TestWarning: def test_warn_config(self, testdir): testdir.makeconftest(""" diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_conftest.py --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,4 +1,5 @@ -import py, pytest +import py +import pytest from _pytest.config import Conftest @@ -13,11 +14,13 @@ tmpdir.ensure("adir/b/__init__.py") return tmpdir + def ConftestWithSetinitial(path): conftest = Conftest() conftest_setinitial(conftest, [path]) return conftest + def conftest_setinitial(conftest, args, confcutdir=None): class Namespace: def __init__(self): @@ -25,6 +28,7 @@ self.confcutdir = str(confcutdir) conftest.setinitial(Namespace()) + class TestConftestValueAccessGlobal: def test_basic_init(self, basedir): conftest = Conftest() @@ -41,12 +45,13 @@ assert conftest.rget_with_confmod("b", adir.join("b"))[1] == 2 assert len(l) == 2 - def test_immediate_initialiation_and_incremental_are_the_same(self, basedir): + def test_immediate_initialiation_and_incremental_are_the_same(self, + basedir): conftest = Conftest() 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')) @@ -68,11 +73,12 @@ 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") @@ -80,6 +86,7 @@ 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() @@ -88,6 +95,7 @@ l = conftest.getconftestmodules(conf) assert len(l) == 1 + def test_issue151_load_all_conftests(testdir): names = "code proj src".split() for name in names: @@ -99,6 +107,7 @@ d = list(conftest._conftestpath2mod.values()) assert len(d) == len(names) + def test_conftest_global_import(testdir): testdir.makeconftest("x=3") p = testdir.makepyfile(""" @@ -120,6 +129,7 @@ res = testdir.runpython(p) assert res.ret == 0 + def test_conftestcutdir(testdir): conf = testdir.makeconftest("") p = testdir.mkdir("x") @@ -139,6 +149,7 @@ assert len(l) == 1 assert l[0].__file__.startswith(str(conf)) + def test_conftestcutdir_inplace_considered(testdir): conf = testdir.makeconftest("") conftest = Conftest() @@ -147,6 +158,7 @@ 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) @@ -154,12 +166,13 @@ conftest = Conftest() 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") @@ -170,6 +183,7 @@ result = testdir.runpytest("-h", "--confcutdir=%s" % x, x) result.stdout.fnmatch_lines(["*--xyz*"]) + def test_conftest_existing_resultlog(testdir): x = testdir.mkdir("tests") x.join("conftest.py").write(py.code.Source(""" @@ -180,6 +194,7 @@ 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(py.code.Source(""" @@ -190,11 +205,13 @@ 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") ct2 = sub.join("conftest.py") ct2.write("") + def impct(p): return p conftest = Conftest() diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_core.py --- a/testing/test_core.py +++ b/testing/test_core.py @@ -1,5 +1,7 @@ -import pytest, py, os -from _pytest.core import * # noqa +import pytest +import py +import os +from _pytest.core import * # noqa from _pytest.config import get_plugin_manager @@ -11,8 +13,8 @@ def test_preparse_args(self): pluginmanager = PluginManager() - pytest.raises(ImportError, lambda: - pluginmanager.consider_preparse(["xyz", "-p", "hello123"])) + with pytest.raises(ImportError): + pluginmanager.consider_preparse(["xyz", "-p", "hello123"]) def test_plugin_prevent_register(self): pluginmanager = PluginManager() @@ -34,7 +36,8 @@ def test_plugin_double_register(self): pm = PluginManager() pm.register(42, name="abc") - pytest.raises(ValueError, lambda: pm.register(42, name="abc")) + with pytest.raises(ValueError): + pm.register(42, name="abc") def test_plugin_skip(self, testdir, monkeypatch): p = testdir.makepyfile(skipping1=""" @@ -66,11 +69,14 @@ def test_consider_setuptools_instantiation(self, monkeypatch): pkg_resources = pytest.importorskip("pkg_resources") + def my_iter(name): assert name == "pytest11" + class EntryPoint: name = "pytest_mytestplugin" dist = None + def load(self): class PseudoPlugin: x = 42 @@ -84,7 +90,8 @@ assert plugin.x == 42 def test_consider_setuptools_not_installed(self, monkeypatch): - monkeypatch.setitem(py.std.sys.modules, 'pkg_resources', + monkeypatch.setitem( + py.std.sys.modules, 'pkg_resources', py.std.types.ModuleType("pkg_resources")) pluginmanager = PluginManager() pluginmanager.consider_setuptools_entrypoints() @@ -105,8 +112,9 @@ def test_import_plugin_importname(self, testdir): pluginmanager = PluginManager() - pytest.raises(ImportError, 'pluginmanager.import_plugin("qweqwex.y")') - pytest.raises(ImportError, 'pluginmanager.import_plugin("pytest_qweqwx.y")') + pytest.raises(ImportError, pluginmanager.import_plugin, "qweqwex.y") + pytest.raises(ImportError, pluginmanager.import_plugin, + "pytest_qweqwx.y") testdir.syspathinsert() pluginname = "pytest_hello" @@ -123,8 +131,9 @@ def test_import_plugin_dotted_name(self, testdir): pluginmanager = PluginManager() - pytest.raises(ImportError, 'pluginmanager.import_plugin("qweqwex.y")') - pytest.raises(ImportError, 'pluginmanager.import_plugin("pytest_qweqwex.y")') + pytest.raises(ImportError, pluginmanager.import_plugin, "qweqwex.y") + pytest.raises(ImportError, pluginmanager.import_plugin, + "pytest_qweqwex.y") testdir.syspathinsert() testdir.mkpydir("pkg").join("plug.py").write("x=3") @@ -150,7 +159,7 @@ aplugin = testdir.makepyfile(pytest_a="#") pluginmanager = get_plugin_manager() reprec = testdir.make_hook_recorder(pluginmanager) - #syspath.prepend(aplugin.dirpath()) + # syspath.prepend(aplugin.dirpath()) py.std.sys.path.insert(0, str(aplugin.dirpath())) pluginmanager.consider_module(mod) call = reprec.getcall(pluginmanager.hook.pytest_plugin_registered.name) @@ -172,7 +181,9 @@ def test_pm(self): pp = PluginManager() - class A: pass + + class A: + pass a1, a2 = A(), A() pp.register(a1) assert pp.isregistered(a1) @@ -187,7 +198,9 @@ def test_pm_ordering(self): pp = PluginManager() - class A: pass + + class A: + pass a1, a2 = A(), A() pp.register(a1) pp.register(a2, "hello") @@ -207,7 +220,7 @@ assert mod in l pytest.raises(ValueError, "pp.register(mod)") pytest.raises(ValueError, lambda: pp.register(mod)) - #assert not pp.isregistered(mod2) + # assert not pp.isregistered(mod2) assert pp.getplugins() == l def test_canonical_import(self, monkeypatch): @@ -220,6 +233,7 @@ def test_register_mismatch_method(self): pp = get_plugin_manager() + class hello: def pytest_gurgel(self): pass @@ -227,6 +241,7 @@ def test_register_mismatch_arg(self): pp = get_plugin_manager() + class hello: def pytest_configure(self, asd): pass @@ -234,6 +249,7 @@ def test_register(self): pm = get_plugin_manager() + class MyPlugin: pass my = MyPlugin() @@ -251,10 +267,13 @@ def test_listattr(self): plugins = PluginManager() + class api1: x = 41 + class api2: x = 42 + class api3: x = 43 plugins.register(api1()) @@ -266,8 +285,10 @@ def test_hook_tracing(self): pm = get_plugin_manager() saveindent = [] + class api1: x = 41 + def pytest_plugin_registered(self, plugin): saveindent.append(pm.trace.root.indent) raise ValueError(42) @@ -285,6 +306,7 @@ assert pm.trace.root.indent == indent assert saveindent[0] > indent + class TestPytestPluginInteractions: def test_addhooks_conftestplugin(self, testdir): @@ -356,6 +378,7 @@ def test_configure(self, testdir): config = testdir.parseconfig() l = [] + class A: def pytest_configure(self, config): l.append(self) @@ -376,6 +399,7 @@ def test_listattr(self): pluginmanager = PluginManager() + class My2: x = 42 pluginmanager.register(My2()) @@ -391,6 +415,7 @@ class P2: def m(self): return 23 + class P3: def m(self): return 19 @@ -418,12 +443,16 @@ result = testdir.runpython(p) assert result.ret == 0 + def test_varnames(): + def f(x): i = 3 # noqa + class A: def f(self, y): pass + class B(object): def __call__(self, z): pass @@ -431,20 +460,25 @@ assert varnames(A().f) == ('y',) assert varnames(B()) == ('z',) + def test_varnames_default(): def f(x, y=3): pass assert varnames(f) == ("x",) + def test_varnames_class(): class C: def __init__(self, x): pass + class D: pass + assert varnames(C) == ("x",) assert varnames(D) == () + class TestMultiCall: def test_uses_copy_of_methods(self): l = [lambda: 42] @@ -479,6 +513,7 @@ def test_keyword_args(self): def f(x): return x + 1 + class A: def f(self, x, y): return x + y @@ -486,7 +521,7 @@ assert "'x': 23" in repr(multicall) assert "'y': 24" in repr(multicall) reslist = multicall.execute() - assert reslist == [24+23, 24] + assert reslist == [24 + 23, 24] assert "2 results" in repr(multicall) def test_keyword_args_with_defaultargs(self): @@ -514,6 +549,7 @@ def test_call_none_is_no_result(self): def m1(): return 1 + def m2(): return None res = MultiCall([m1, m2], {}, firstresult=True).execute() @@ -523,6 +559,7 @@ def test_hookwrapper(self): l = [] + def m1(): l.append("m1 init") yield None @@ -542,6 +579,7 @@ def test_hookwrapper_order(self): l = [] + def m1(): l.append("m1 init") yield 1 @@ -581,10 +619,10 @@ pluginmanager.register(p3) methods = pluginmanager.listattr('m') assert methods == [p2.m, p3.m, p1.m] - ## listattr keeps a cache and deleting - ## a function attribute requires clearing it - #pluginmanager._listattrcache.clear() - #del P1.m.__dict__['tryfirst'] + # # listattr keeps a cache and deleting + # # a function attribute requires clearing it + # pluginmanager._listattrcache.clear() + # del P1.m.__dict__['tryfirst'] def test_hookwrapper_not_yield(self): def m1(): @@ -617,6 +655,7 @@ hook = pm.hook assert hasattr(hook, 'hello') assert repr(hook.hello).find("hello") != -1 + class Plugin: def hello(self, arg): return arg + 1 @@ -633,6 +672,7 @@ def hello(self, arg): "api hook 1" pm = PluginManager(Api, prefix="he") + class Plugin: def hello(self, argwrong): return arg + 1 @@ -642,6 +682,7 @@ def test_only_kwargs(self): pm = PluginManager() + class Api: def hello(self, arg): "api hook 1" @@ -654,6 +695,7 @@ "api hook 1" hello.firstresult = True pm = PluginManager([Api], "he") + class Plugin: def hello(self, arg): return arg + 1 @@ -661,6 +703,7 @@ res = pm.hook.hello(arg=3) assert res == 4 + class TestTracer: def test_simple(self): from _pytest.core import TagTracer @@ -695,8 +738,9 @@ log("last") assert len(l) == 7 names = [x[:x.rfind(' [')] for x in l] - assert names == ['hello', ' line1', ' line2', - ' line3', ' line4', ' line5', 'last'] + assert names == [ + 'hello', ' line1', ' line2', + ' line3', ' line4', ' line5', 'last'] def test_readable_output_dictargs(self): from _pytest.core import TagTracer @@ -705,8 +749,8 @@ out = rootlogger.format_message(['test'], [1]) assert out == ['1 [test]\n'] - out2= rootlogger.format_message(['test'], ['test', {'a':1}]) - assert out2 ==[ + out2 = rootlogger.format_message(['test'], ['test', {'a': 1}]) + assert out2 == [ 'test [test]\n', ' a: 1\n' ] @@ -716,7 +760,7 @@ rootlogger = TagTracer() log = rootlogger.get("1") log2 = log.get("2") - assert log2.tags == tuple("12") + assert log2.tags == tuple("12") l = [] rootlogger.setprocessor(tuple("12"), lambda *args: l.append(args)) log("not seen") @@ -732,7 +776,6 @@ tags, args = l2[0] assert args == ("seen",) - def test_setmyprocessor(self): from _pytest.core import TagTracer rootlogger = TagTracer() @@ -749,6 +792,7 @@ assert "2" in tags assert args == (42,) + def test_default_markers(testdir): result = testdir.runpytest("--markers") result.stdout.fnmatch_lines([ @@ -756,12 +800,14 @@ "*trylast*last*", ]) + def test_importplugin_issue375(testdir): testdir.makepyfile(qwe="import aaaa") excinfo = pytest.raises(ImportError, lambda: importplugin("qwe")) assert "qwe" not in str(excinfo.value) assert "aaaa" in str(excinfo.value) + class TestWrapMethod: def test_basic_happypath(self): class A: @@ -769,6 +815,7 @@ return "A.f" l = [] + def f(self): l.append(1) box = yield @@ -777,7 +824,7 @@ undo = add_method_wrapper(A, f) assert A().f() == "A.f" - assert l == [1,2] + assert l == [1, 2] undo() l[:] = [] assert A().f() == "A.f" @@ -805,6 +852,7 @@ raise ValueError(val) l = [] + def error(self, val): l.append(val) yield @@ -852,9 +900,10 @@ def test_modify_call_args(self): class A: def error(self, val1, val2): - raise ValueError(val1+val2) + raise ValueError(val1 + val2) l = [] + def error(self): box = yield (1,), {'val2': 2} assert box.excinfo[1].args == (3,) diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,10 +1,15 @@ from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile -import py, pytest +import py +import pytest import pdb -xfail_if_pdbpp_installed = pytest.mark.xfail(hasattr(pdb, "__author__"), - reason="doctest/pdbpp problem: https://bitbucket.org/antocuni/pdb/issue/24/doctests-fail-when-pdbpp-is-installed", run=False) +xfail_if_pdbpp_installed = pytest.mark.xfail( + hasattr(pdb, "__author__"), + reason="doctest/pdbpp problem: " + "https://bitbucket.org/antocuni/pdb/issue/24/" + "doctests-fail-when-pdbpp-is-installed", run=False) + class TestDoctests: @@ -17,7 +22,7 @@ 4 """) 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], DoctestTextfile) @@ -27,15 +32,13 @@ def test_collect_module_empty(self, testdir): path = testdir.makepyfile(whatever="#") for p in (path, testdir.tmpdir): - items, reprec = testdir.inline_genitems(p, - '--doctest-modules') + items, reprec = testdir.inline_genitems(p, '--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') + items, reprec = testdir.inline_genitems(p, '--doctest-modules') assert len(items) == 1 assert isinstance(items[0], DoctestItem) assert isinstance(items[0].parent, DoctestModule) @@ -47,8 +50,7 @@ ">>> magic = 42 " """) for p in (path, testdir.tmpdir): - items, reprec = testdir.inline_genitems(p, - '--doctest-modules') + items, reprec = testdir.inline_genitems(p, '--doctest-modules') assert len(items) == 2 assert isinstance(items[0], DoctestItem) assert isinstance(items[1], DoctestItem) @@ -72,16 +74,15 @@ ''' """) for p in (path, testdir.tmpdir): - items, reprec = testdir.inline_genitems(p, - '--doctest-modules') + items, reprec = testdir.inline_genitems(p, '--doctest-modules') assert len(items) == 2 assert isinstance(items[0], DoctestItem) assert isinstance(items[1], DoctestItem) assert isinstance(items[0].parent, DoctestModule) assert items[0].parent is items[1].parent - @pytest.mark.xfail('hasattr(sys, "pypy_version_info")', reason= - "pypy leaks one FD") + @pytest.mark.xfail('hasattr(sys, "pypy_version_info")', + reason="pypy leaks one FD") def test_simple_doctestfile(self, testdir): p = testdir.maketxtfile(test_doc=""" >>> x = 1 @@ -92,7 +93,7 @@ reprec.assertoutcome(failed=1) def test_new_pattern(self, testdir): - p = testdir.maketxtfile(xdoc =""" + p = testdir.maketxtfile(xdoc=""" >>> x = 1 >>> x == 1 False @@ -127,13 +128,13 @@ result = testdir.runpytest("--doctest-modules") result.stdout.fnmatch_lines([ "*hello*", - "*EXAMPLE LOCATION UNKNOWN, not showing all tests of that example*", + "*EXAMPLE LOCATION UNKNOWN, " + "not showing all tests of that example*", "*1/0*", "*UNEXPECTED*ZeroDivision*", "*1 failed*", ]) - def test_doctest_unex_importerror(self, testdir): testdir.tmpdir.join("hello.py").write(py.code.Source(""" import asdalsdkjaslkdjasd @@ -183,7 +184,6 @@ "*:5: DocTestFailure" ]) - def test_txtfile_failing(self, testdir): p = testdir.maketxtfile(""" >>> i = 0 diff -r eb3382c1cf5061a70396445727c1ca8102be95f3 -r 60e93163ce6fc37867fe22c1d243306215b490b2 testing/test_genscript.py --- a/testing/test_genscript.py +++ b/testing/test_genscript.py @@ -6,6 +6,7 @@ def standalone(request): return Standalone(request) + class Standalone: def __init__(self, request): self.testdir = request.getfuncargvalue("testdir") @@ -19,10 +20,11 @@ testdir.chdir() return testdir._run(anypython, self.script, *args) + def test_gen(testdir, anypython, standalone): - if sys.version_info >= (2,7): + if sys.version_info >= (2, 7): result = testdir._run(anypython, "-c", - "import sys;print (sys.version_info >=(2,7))") + "import sys;print (sys.version_info >=(2, 7))") assert result.ret == 0 if result.stdout.str() == "False": pytest.skip("genscript called from python2.7 cannot work " @@ -45,4 +47,3 @@ includes = pytest.freeze_includes() assert len(includes) > 1 assert '_pytest.genscript' in includes - This diff is so big that we needed to truncate the remainder. https://bitbucket.org/hpk42/pytest/commits/6f78944be6a2/ Changeset: 6f78944be6a2 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 18:07:29+00:00 Summary: finish flake8 clean Affected #: 1 file diff -r 60e93163ce6fc37867fe22c1d243306215b490b2 -r 6f78944be6a29393f796f7e1cd266abad32f694d setup.py --- a/setup.py +++ b/setup.py @@ -2,17 +2,20 @@ import sys from setuptools import setup, Command -classifiers = ['Development Status :: 6 - Mature', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Operating System :: POSIX', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: MacOS :: MacOS X', - 'Topic :: Software Development :: Testing', - 'Topic :: Software Development :: Libraries', - 'Topic :: Utilities'] + [ - ('Programming Language :: Python :: %s' % x) - for x in '2 2.6 2.7 3 3.2 3.3 3.4'.split()] +classifiers = [ + 'Development Status :: 6 - Mature', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Operating System :: POSIX', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: MacOS :: MacOS X', + 'Topic :: Software Development :: Testing', + 'Topic :: Software Development :: Libraries', + 'Topic :: Utilities', +] + [ + ('Programming Language :: Python :: %s' % x) + for x in '2 2.6 2.7 3 3.2 3.3 3.4'.split() +] long_description = open('README.rst').read() Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sun Feb 22 19:13:11 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 18:13:11 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150222181311.10479.47651@app13.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/bdfb2bb4066a/ Changeset: bdfb2bb4066a Branch: junit-verbose-failures User: tush home Date: 2015-01-19 22:45:26+00:00 Summary: Failure message in junit xml report now are more informative Affected #: 2 files diff -r d91265465608bd3777ab0c882e5d68335d7472dd -r bdfb2bb4066af8e97a341dddf7c595f6d9e05035 _pytest/junitxml.py --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -123,7 +123,12 @@ Junit.skipped(message="xfail-marked test passes unexpectedly")) self.skipped += 1 else: - fail = Junit.failure(message="test failure") + if isinstance(report.longrepr, (unicode, str)): + message = report.longrepr + else: + message = report.longrepr.reprcrash.message + message = bin_xml_escape(message) + fail = Junit.failure(message=message) fail.append(bin_xml_escape(report.longrepr)) self.append(fail) self.failed += 1 diff -r d91265465608bd3777ab0c882e5d68335d7472dd -r bdfb2bb4066af8e97a341dddf7c595f6d9e05035 testing/test_junitxml.py --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -150,7 +150,7 @@ classname="test_failure_function", name="test_fail") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="ValueError: 42") assert "ValueError" in fnode.toxml() systemout = fnode.nextSibling assert systemout.tagName == "system-out" @@ -159,6 +159,19 @@ assert systemerr.tagName == "system-err" assert "hello-stderr" in systemerr.toxml() + def test_failure_verbose_message(self, testdir): + testdir.makepyfile(""" + import sys + def test_fail(): + assert 0, "An error" + """) + + result, dom = runandparse(testdir) + node = dom.getElementsByTagName("testsuite")[0] + tnode = node.getElementsByTagName("testcase")[0] + fnode = tnode.getElementsByTagName("failure")[0] + assert_attr(fnode, message="AssertionError: An error assert 0") + def test_failure_escape(self, testdir): testdir.makepyfile(""" import pytest @@ -371,7 +384,7 @@ #classname="test_collect_error", name="myfile.xyz") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="custom item runtest failed") assert "custom item runtest failed" in fnode.toxml() https://bitbucket.org/hpk42/pytest/commits/dc7e08bec905/ Changeset: dc7e08bec905 User: RonnyPfannschmidt Date: 2015-02-22 18:13:07+00:00 Summary: Merged in tush/pytest/junit-verbose-failures (pull request #240) Made failure message in junit xml report more informative Affected #: 2 files diff -r 181d08e03c11f34aac5f3358a92cc4d1d5557963 -r dc7e08bec9055b8a0ecc5575499847371e2b9cfb _pytest/junitxml.py --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -123,7 +123,12 @@ Junit.skipped(message="xfail-marked test passes unexpectedly")) self.skipped += 1 else: - fail = Junit.failure(message="test failure") + if isinstance(report.longrepr, (unicode, str)): + message = report.longrepr + else: + message = report.longrepr.reprcrash.message + message = bin_xml_escape(message) + fail = Junit.failure(message=message) fail.append(bin_xml_escape(report.longrepr)) self.append(fail) self.failed += 1 diff -r 181d08e03c11f34aac5f3358a92cc4d1d5557963 -r dc7e08bec9055b8a0ecc5575499847371e2b9cfb testing/test_junitxml.py --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -150,7 +150,7 @@ classname="test_failure_function", name="test_fail") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="ValueError: 42") assert "ValueError" in fnode.toxml() systemout = fnode.nextSibling assert systemout.tagName == "system-out" @@ -159,6 +159,19 @@ assert systemerr.tagName == "system-err" assert "hello-stderr" in systemerr.toxml() + def test_failure_verbose_message(self, testdir): + testdir.makepyfile(""" + import sys + def test_fail(): + assert 0, "An error" + """) + + result, dom = runandparse(testdir) + node = dom.getElementsByTagName("testsuite")[0] + tnode = node.getElementsByTagName("testcase")[0] + fnode = tnode.getElementsByTagName("failure")[0] + assert_attr(fnode, message="AssertionError: An error assert 0") + def test_failure_escape(self, testdir): testdir.makepyfile(""" import pytest @@ -371,7 +384,7 @@ #classname="test_collect_error", name="myfile.xyz") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="custom item runtest failed") assert "custom item runtest failed" in fnode.toxml() Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sun Feb 22 19:13:12 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 18:13:12 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: Merged in tush/pytest/junit-verbose-failures (pull request #240) Message-ID: <20150222181312.26013.81585@app08.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/dc7e08bec905/ Changeset: dc7e08bec905 User: RonnyPfannschmidt Date: 2015-02-22 18:13:07+00:00 Summary: Merged in tush/pytest/junit-verbose-failures (pull request #240) Made failure message in junit xml report more informative Affected #: 2 files diff -r 181d08e03c11f34aac5f3358a92cc4d1d5557963 -r dc7e08bec9055b8a0ecc5575499847371e2b9cfb _pytest/junitxml.py --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -123,7 +123,12 @@ Junit.skipped(message="xfail-marked test passes unexpectedly")) self.skipped += 1 else: - fail = Junit.failure(message="test failure") + if isinstance(report.longrepr, (unicode, str)): + message = report.longrepr + else: + message = report.longrepr.reprcrash.message + message = bin_xml_escape(message) + fail = Junit.failure(message=message) fail.append(bin_xml_escape(report.longrepr)) self.append(fail) self.failed += 1 diff -r 181d08e03c11f34aac5f3358a92cc4d1d5557963 -r dc7e08bec9055b8a0ecc5575499847371e2b9cfb testing/test_junitxml.py --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -150,7 +150,7 @@ classname="test_failure_function", name="test_fail") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="ValueError: 42") assert "ValueError" in fnode.toxml() systemout = fnode.nextSibling assert systemout.tagName == "system-out" @@ -159,6 +159,19 @@ assert systemerr.tagName == "system-err" assert "hello-stderr" in systemerr.toxml() + def test_failure_verbose_message(self, testdir): + testdir.makepyfile(""" + import sys + def test_fail(): + assert 0, "An error" + """) + + result, dom = runandparse(testdir) + node = dom.getElementsByTagName("testsuite")[0] + tnode = node.getElementsByTagName("testcase")[0] + fnode = tnode.getElementsByTagName("failure")[0] + assert_attr(fnode, message="AssertionError: An error assert 0") + def test_failure_escape(self, testdir): testdir.makepyfile(""" import pytest @@ -371,7 +384,7 @@ #classname="test_collect_error", name="myfile.xyz") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="custom item runtest failed") assert "custom item runtest failed" in fnode.toxml() Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 19:16:07 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 18:16:07 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 383 Message-ID: <20150222181607.4020.72352@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/383 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3864:6f78944be6a2 Author : Ronny Pfannschmidt Branch : flake8-clean Message: finish flake8 clean -------------- next part -------------- An HTML attachment was scrubbed... URL: From issues-reply at bitbucket.org Sun Feb 22 19:18:15 2015 From: issues-reply at bitbucket.org (Ronny Pfannschmidt) Date: Sun, 22 Feb 2015 18:18:15 -0000 Subject: [Pytest-commit] Issue #685: more detailed platform information (hpk42/pytest) Message-ID: <20150222181815.31789.17969@app11.ash-private.bitbucket.org> New issue 685: more detailed platform information https://bitbucket.org/hpk42/pytest/issue/685/more-detailed-platform-information Ronny Pfannschmidt: as noted in pull request #236 we need better detail in the platform/architecture hook From commits-noreply at bitbucket.org Sun Feb 22 20:04:10 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 19:04:10 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150222190410.16735.65514@app03.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/64aa813b3a05/ Changeset: 64aa813b3a05 User: lucas_cimon Date: 2015-02-13 23:07:19+00:00 Summary: Fixing description of --dist=load in the --help documentation for the xdist plugin Affected #: 1 file diff -r 5fc366c50b56a94638c959be8456d2cb3c7e7c1c -r 64aa813b3a05bf7aaeebda81c3c62a7fe498b76c doc/en/test/plugin/xdist.txt --- a/doc/en/test/plugin/xdist.txt +++ b/doc/en/test/plugin/xdist.txt @@ -159,7 +159,7 @@ each: send each test to each available environment. - load: send each test to available environment. + load: send each test to one available environment so it is run only once. (default) no: run tests inprocess, don't distribute. ``--tx=xspec`` https://bitbucket.org/hpk42/pytest/commits/4e32db33cb49/ Changeset: 4e32db33cb49 User: RonnyPfannschmidt Date: 2015-02-22 19:04:05+00:00 Summary: Merged in LucasC/pytest (pull request #247) Fixing description of --dist=load in the --help documentation for the xdist plugin Affected #: 1 file diff -r dc7e08bec9055b8a0ecc5575499847371e2b9cfb -r 4e32db33cb496587858c04818c48adc1112d86d8 doc/en/test/plugin/xdist.txt --- a/doc/en/test/plugin/xdist.txt +++ b/doc/en/test/plugin/xdist.txt @@ -159,7 +159,7 @@ each: send each test to each available environment. - load: send each test to available environment. + load: send each test to one available environment so it is run only once. (default) no: run tests inprocess, don't distribute. ``--tx=xspec`` Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sun Feb 22 20:04:10 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 19:04:10 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: Merged in LucasC/pytest (pull request #247) Message-ID: <20150222190410.26239.44229@app13.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/4e32db33cb49/ Changeset: 4e32db33cb49 User: RonnyPfannschmidt Date: 2015-02-22 19:04:05+00:00 Summary: Merged in LucasC/pytest (pull request #247) Fixing description of --dist=load in the --help documentation for the xdist plugin Affected #: 1 file diff -r dc7e08bec9055b8a0ecc5575499847371e2b9cfb -r 4e32db33cb496587858c04818c48adc1112d86d8 doc/en/test/plugin/xdist.txt --- a/doc/en/test/plugin/xdist.txt +++ b/doc/en/test/plugin/xdist.txt @@ -159,7 +159,7 @@ each: send each test to each available environment. - load: send each test to available environment. + load: send each test to one available environment so it is run only once. (default) no: run tests inprocess, don't distribute. ``--tx=xspec`` Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sun Feb 22 20:37:00 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 19:37:00 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: merge from default Message-ID: <20150222193700.6353.7890@app13.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/c1c1bb35c519/ Changeset: c1c1bb35c519 Branch: flake8-clean User: RonnyPfannschmidt Date: 2015-02-22 19:35:14+00:00 Summary: merge from default Affected #: 28 files diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e .hgtags --- a/.hgtags +++ b/.hgtags @@ -72,3 +72,4 @@ a4f9639702baa3eb4f3b16e162f74f7b69f3f9e1 2.6.1 a4f25c5e649892b5cc746d21be971e4773478af9 2.6.2 2967aa416a4f3cdb65fc75073a2a148e1f372742 2.6.3 +f03b6de8325f5b6c35cea7c3de092f134ea8ef07 2.6.4 diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -57,6 +57,12 @@ - fix issue614: fixed pastebin support. + +- fix issue620: add explanation in the --genscript target about what + the binary blob means. Thanks Dinu Gherman. + +- fix issue614: fixed pastebin support. + 2.6.3 ----------- diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e _pytest/junitxml.py --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -133,7 +133,12 @@ Junit.skipped(message="xfail-marked test passes unexpectedly")) self.skipped += 1 else: - fail = Junit.failure(message="test failure") + if isinstance(report.longrepr, (unicode, str)): + message = report.longrepr + else: + message = report.longrepr.reprcrash.message + message = bin_xml_escape(message) + fail = Junit.failure(message=message) fail.append(bin_xml_escape(report.longrepr)) self.append(fail) self.failed += 1 diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/assert.txt --- a/doc/en/assert.txt +++ b/doc/en/assert.txt @@ -26,7 +26,7 @@ $ py.test test_assert1.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_assert1.py F @@ -135,7 +135,7 @@ $ py.test test_assert2.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_assert2.py F @@ -152,6 +152,7 @@ E '1' E Extra items in the right set: E '5' + E Use -v to get the full diff test_assert2.py:5: AssertionError ========================= 1 failed in 0.01 seconds ========================= diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/capture.txt --- a/doc/en/capture.txt +++ b/doc/en/capture.txt @@ -64,7 +64,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py .F @@ -78,7 +78,7 @@ test_module.py:9: AssertionError -------------------------- Captured stdout setup --------------------------- - setting up + setting up ==================== 1 failed, 1 passed in 0.01 seconds ==================== Accessing captured output from a test function diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/conf.py --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -18,7 +18,7 @@ # The full version, including alpha/beta/rc tags. # The short X.Y version. version = "2.6" -release = "2.6.3" +release = "2.6.4" import sys, os diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/doctest.txt --- a/doc/en/doctest.txt +++ b/doc/en/doctest.txt @@ -44,12 +44,12 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items mymodule.py . - ========================= 1 passed in 0.05 seconds ========================= + ========================= 1 passed in 0.06 seconds ========================= It is possible to use fixtures using the ``getfixture`` helper:: diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/example/markers.txt --- a/doc/en/example/markers.txt +++ b/doc/en/example/markers.txt @@ -31,7 +31,7 @@ $ py.test -v -m webtest =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_send_http PASSED @@ -43,7 +43,7 @@ $ py.test -v -m "not webtest" =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_something_quick PASSED @@ -62,7 +62,7 @@ $ py.test -v test_server.py::TestClass::test_method =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 5 items test_server.py::TestClass::test_method PASSED @@ -73,7 +73,7 @@ $ py.test -v test_server.py::TestClass =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::TestClass::test_method PASSED @@ -84,7 +84,7 @@ $ py.test -v test_server.py::TestClass test_server.py::test_send_http =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 8 items test_server.py::TestClass::test_method PASSED @@ -120,7 +120,7 @@ $ py.test -v -k http # running with the above defined example module =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_send_http PASSED @@ -132,7 +132,7 @@ $ py.test -k "not send_http" -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_something_quick PASSED @@ -140,13 +140,13 @@ test_server.py::TestClass::test_method PASSED ================= 1 tests deselected by '-knot send_http' ================== - ================== 3 passed, 1 deselected in 0.02 seconds ================== + ================== 3 passed, 1 deselected in 0.01 seconds ================== Or to select "http" and "quick" tests:: $ py.test -k "http or quick" -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 4 items test_server.py::test_send_http PASSED @@ -334,7 +334,7 @@ $ py.test -E stage2 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_someenv.py s @@ -345,7 +345,7 @@ $ py.test -E stage1 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_someenv.py . @@ -463,12 +463,12 @@ $ py.test -rs # this option reports skip reasons =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_plat.py sss. ========================= short test summary info ========================== - SKIP [3] /tmp/doc-exec-224/conftest.py:12: cannot run on platform linux + SKIP [3] /tmp/doc-exec-68/conftest.py:12: cannot run on platform linux =================== 1 passed, 3 skipped in 0.01 seconds ==================== @@ -476,7 +476,7 @@ $ py.test -m linux2 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_plat.py s @@ -527,7 +527,7 @@ $ py.test -m interface --tb=short =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_module.py FF @@ -548,7 +548,7 @@ $ py.test -m "interface or event" --tb=short =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_module.py FFF diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/example/nonpython.txt --- a/doc/en/example/nonpython.txt +++ b/doc/en/example/nonpython.txt @@ -27,10 +27,10 @@ nonpython $ py.test test_simple.yml =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items - test_simple.yml .F + test_simple.yml F. ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ @@ -56,11 +56,11 @@ nonpython $ py.test -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 2 items + test_simple.yml::usecase: hello FAILED test_simple.yml::usecase: ok PASSED - test_simple.yml::usecase: hello FAILED ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ @@ -74,10 +74,10 @@ nonpython $ py.test --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items + - ============================= in 0.03 seconds ============================= diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/example/parametrize.txt --- a/doc/en/example/parametrize.txt +++ b/doc/en/example/parametrize.txt @@ -181,7 +181,7 @@ $ py.test test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_scenarios.py .... @@ -193,7 +193,7 @@ $ py.test --collect-only test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items @@ -257,7 +257,7 @@ $ py.test test_backends.py --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items @@ -272,7 +272,7 @@ ================================= FAILURES ================================= _________________________ test_db_initialized[d2] __________________________ - db = + db = def test_db_initialized(db): # a dummy test @@ -281,7 +281,7 @@ E Failed: deliberately failing for demo purposes test_backends.py:6: Failed - 1 failed, 1 passed in 0.02 seconds + 1 failed, 1 passed in 0.01 seconds The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``db`` fixture function has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase. @@ -326,16 +326,16 @@ $ py.test -q F.. ================================= FAILURES ================================= - ________________________ TestClass.test_equals[1-2] ________________________ + ________________________ TestClass.test_equals[2-1] ________________________ - self = , a = 1, b = 2 + self = , a = 1, b = 2 def test_equals(self, a, b): > assert a == b E assert 1 == 2 test_parametrize.py:18: AssertionError - 1 failed, 2 passed in 0.02 seconds + 1 failed, 2 passed in 0.01 seconds Indirect parametrization with multiple fixtures -------------------------------------------------------------- @@ -358,8 +358,8 @@ ================================= FAILURES ================================= ________________ test_basic_objects[python3.4-python2.6-42] ________________ - python1 = - python2 = , obj = 42 + python1 = + python2 = , obj = 42 @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -372,7 +372,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py' + cmd = '/home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p0/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -397,9 +397,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p0/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p0/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p0/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.6/pickle.py", line 1370, in load E return Unpickler(file).load() @@ -411,11 +411,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p0/load.py _______________ test_basic_objects[python3.4-python2.6-obj1] _______________ - python1 = - python2 = , obj = {} + python1 = + python2 = , obj = {} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -428,7 +428,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py' + cmd = '/home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p1/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -453,9 +453,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p1/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p1/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p1/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.6/pickle.py", line 1370, in load E return Unpickler(file).load() @@ -467,11 +467,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p1/load.py _______________ test_basic_objects[python3.4-python2.6-obj2] _______________ - python1 = - python2 = , obj = {1: 3} + python1 = + python2 = , obj = {1: 3} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -484,7 +484,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py' + cmd = '/home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p2/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -509,9 +509,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-111/test_basic_objects_python3_4_p2/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p2/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p2/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.6/pickle.py", line 1370, in load E return Unpickler(file).load() @@ -523,11 +523,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p2/load.py ________________ test_basic_objects[python3.4-python2.7-42] ________________ - python1 = - python2 = , obj = 42 + python1 = + python2 = , obj = 42 @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -540,7 +540,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py' + cmd = '/home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p3/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -565,9 +565,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p3/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p3/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p3/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.7/pickle.py", line 1378, in load E return Unpickler(file).load() @@ -579,11 +579,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p3/load.py _______________ test_basic_objects[python3.4-python2.7-obj1] _______________ - python1 = - python2 = , obj = {} + python1 = + python2 = , obj = {} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -596,7 +596,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py' + cmd = '/home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p4/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -621,9 +621,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p4/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p4/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p4/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.7/pickle.py", line 1378, in load E return Unpickler(file).load() @@ -635,11 +635,11 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py + /tmp/pytest-111/test_basic_objects_python3_4_p4/load.py _______________ test_basic_objects[python3.4-python2.7-obj2] _______________ - python1 = - python2 = , obj = {1: 3} + python1 = + python2 = , obj = {1: 3} @pytest.mark.parametrize("obj", [42, {}, {1:3},]) def test_basic_objects(python1, python2, obj): @@ -652,7 +652,7 @@ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile)) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py' + cmd = '/home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p5/load.py' def cmdexec(cmd): """ return unicode output of executing 'cmd' in a separate process. @@ -677,9 +677,9 @@ status = process.poll() if status: > raise ExecutionFailed(status, status, cmd, out, err) - E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py + E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/venv/0/bin/python2.7 /tmp/pytest-111/test_basic_objects_python3_4_p5/load.py E Traceback (most recent call last): - E File "/tmp/pytest-21/test_basic_objects_python3_4_p5/load.py", line 4, in + E File "/tmp/pytest-111/test_basic_objects_python3_4_p5/load.py", line 4, in E obj = pickle.load(f) E File "/usr/lib/python2.7/pickle.py", line 1378, in load E return Unpickler(file).load() @@ -691,8 +691,8 @@ ../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error --------------------------- Captured stdout call --------------------------- - /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py - 6 failed, 21 passed in 1.36 seconds + /tmp/pytest-111/test_basic_objects_python3_4_p5/load.py + 6 failed, 21 passed in 1.66 seconds Indirect parametrization of optional implementations/imports -------------------------------------------------------------------- @@ -739,12 +739,12 @@ $ py.test -rs test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py .s ========================= short test summary info ========================== - SKIP [1] /tmp/doc-exec-226/conftest.py:10: could not import 'opt2' + SKIP [1] /tmp/doc-exec-70/conftest.py:10: could not import 'opt2' =================== 1 passed, 1 skipped in 0.01 seconds ==================== diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/example/pythoncollection.txt --- a/doc/en/example/pythoncollection.txt +++ b/doc/en/example/pythoncollection.txt @@ -43,7 +43,7 @@ $ py.test --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items @@ -88,7 +88,7 @@ . $ py.test --collect-only pythoncollection.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items @@ -141,10 +141,10 @@ $ py.test --collect-only =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 0 items - ============================= in 0.01 seconds ============================= + ============================= in 0.00 seconds ============================= If you run with a Python3 interpreter the moduled added through the conftest.py file will not be considered for test collection. diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/example/reportingdemo.txt --- a/doc/en/example/reportingdemo.txt +++ b/doc/en/example/reportingdemo.txt @@ -13,7 +13,7 @@ assertion $ py.test failure_demo.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 42 items failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF @@ -30,7 +30,7 @@ failure_demo.py:15: AssertionError _________________________ TestFailing.test_simple __________________________ - self = + self = def test_simple(self): def f(): @@ -40,13 +40,13 @@ > assert f() == g() E assert 42 == 43 - E + where 42 = .f at 0x2adb9887e6a8>() - E + and 43 = .g at 0x2adb9887e598>() + E + where 42 = .f at 0x2b4436f1e6a8>() + E + and 43 = .g at 0x2b4436f1e7b8>() failure_demo.py:28: AssertionError ____________________ TestFailing.test_simple_multiline _____________________ - self = + self = def test_simple_multiline(self): otherfunc_multi( @@ -66,19 +66,19 @@ failure_demo.py:11: AssertionError ___________________________ TestFailing.test_not ___________________________ - self = + self = def test_not(self): def f(): return 42 > assert not f() E assert not 42 - E + where 42 = .f at 0x2adb9887e840>() + E + where 42 = .f at 0x2b4436f1ebf8>() failure_demo.py:38: AssertionError _________________ TestSpecialisedExplanations.test_eq_text _________________ - self = + self = def test_eq_text(self): > assert 'spam' == 'eggs' @@ -89,7 +89,7 @@ failure_demo.py:42: AssertionError _____________ TestSpecialisedExplanations.test_eq_similar_text _____________ - self = + self = def test_eq_similar_text(self): > assert 'foo 1 bar' == 'foo 2 bar' @@ -102,7 +102,7 @@ failure_demo.py:45: AssertionError ____________ TestSpecialisedExplanations.test_eq_multiline_text ____________ - self = + self = def test_eq_multiline_text(self): > assert 'foo\nspam\nbar' == 'foo\neggs\nbar' @@ -115,7 +115,7 @@ failure_demo.py:48: AssertionError ______________ TestSpecialisedExplanations.test_eq_long_text _______________ - self = + self = def test_eq_long_text(self): a = '1'*100 + 'a' + '2'*100 @@ -132,7 +132,7 @@ failure_demo.py:53: AssertionError _________ TestSpecialisedExplanations.test_eq_long_text_multiline __________ - self = + self = def test_eq_long_text_multiline(self): a = '1\n'*100 + 'a' + '2\n'*100 @@ -156,17 +156,18 @@ failure_demo.py:58: AssertionError _________________ TestSpecialisedExplanations.test_eq_list _________________ - self = + self = def test_eq_list(self): > assert [0, 1, 2] == [0, 1, 3] E assert [0, 1, 2] == [0, 1, 3] E At index 2 diff: 2 != 3 + E Use -v to get the full diff failure_demo.py:61: AssertionError ______________ TestSpecialisedExplanations.test_eq_list_long _______________ - self = + self = def test_eq_list_long(self): a = [0]*100 + [1] + [3]*100 @@ -174,11 +175,12 @@ > assert a == b E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...] E At index 100 diff: 1 != 2 + E Use -v to get the full diff failure_demo.py:66: AssertionError _________________ TestSpecialisedExplanations.test_eq_dict _________________ - self = + self = def test_eq_dict(self): > assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0} @@ -190,11 +192,12 @@ E {'c': 0} E Right contains more items: E {'d': 0} + E Use -v to get the full diff failure_demo.py:69: AssertionError _________________ TestSpecialisedExplanations.test_eq_set __________________ - self = + self = def test_eq_set(self): > assert set([0, 10, 11, 12]) == set([0, 20, 21]) @@ -206,21 +209,23 @@ E Extra items in the right set: E 20 E 21 + E Use -v to get the full diff failure_demo.py:72: AssertionError _____________ TestSpecialisedExplanations.test_eq_longer_list ______________ - self = + self = def test_eq_longer_list(self): > assert [1,2] == [1,2,3] E assert [1, 2] == [1, 2, 3] E Right contains more items, first extra item: 3 + E Use -v to get the full diff failure_demo.py:75: AssertionError _________________ TestSpecialisedExplanations.test_in_list _________________ - self = + self = def test_in_list(self): > assert 1 in [0, 2, 3, 4, 5] @@ -229,7 +234,7 @@ failure_demo.py:78: AssertionError __________ TestSpecialisedExplanations.test_not_in_text_multiline __________ - self = + self = def test_not_in_text_multiline(self): text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail' @@ -247,7 +252,7 @@ failure_demo.py:82: AssertionError ___________ TestSpecialisedExplanations.test_not_in_text_single ____________ - self = + self = def test_not_in_text_single(self): text = 'single foo line' @@ -260,7 +265,7 @@ failure_demo.py:86: AssertionError _________ TestSpecialisedExplanations.test_not_in_text_single_long _________ - self = + self = def test_not_in_text_single_long(self): text = 'head ' * 50 + 'foo ' + 'tail ' * 20 @@ -273,7 +278,7 @@ failure_demo.py:90: AssertionError ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______ - self = + self = def test_not_in_text_single_long_term(self): text = 'head ' * 50 + 'f'*70 + 'tail ' * 20 @@ -292,7 +297,7 @@ i = Foo() > assert i.b == 2 E assert 1 == 2 - E + where 1 = .Foo object at 0x2adb987b5470>.b + E + where 1 = .Foo object at 0x2b4436e42ac8>.b failure_demo.py:101: AssertionError _________________________ test_attribute_instance __________________________ @@ -302,8 +307,8 @@ b = 1 > assert Foo().b == 2 E assert 1 == 2 - E + where 1 = .Foo object at 0x2adb987d0390>.b - E + where .Foo object at 0x2adb987d0390> = .Foo'>() + E + where 1 = .Foo object at 0x2b4436f185c0>.b + E + where .Foo object at 0x2b4436f185c0> = .Foo'>() failure_demo.py:107: AssertionError __________________________ test_attribute_failure __________________________ @@ -319,7 +324,7 @@ failure_demo.py:116: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - self = .Foo object at 0x2adb98822cf8> + self = .Foo object at 0x2b4436f16a58> def _get_b(self): > raise Exception('Failed to get attrib') @@ -335,15 +340,15 @@ b = 2 > assert Foo().b == Bar().b E assert 1 == 2 - E + where 1 = .Foo object at 0x2adb98841dd8>.b - E + where .Foo object at 0x2adb98841dd8> = .Foo'>() - E + and 2 = .Bar object at 0x2adb98841a90>.b - E + where .Bar object at 0x2adb98841a90> = .Bar'>() + E + where 1 = .Foo object at 0x2b4436f12a90>.b + E + where .Foo object at 0x2b4436f12a90> = .Foo'>() + E + and 2 = .Bar object at 0x2b4436f12ac8>.b + E + where .Bar object at 0x2b4436f12ac8> = .Bar'>() failure_demo.py:124: AssertionError __________________________ TestRaises.test_raises __________________________ - self = + self = def test_raises(self): s = 'qwe' @@ -358,7 +363,7 @@ <0-codegen /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1028>:1: ValueError ______________________ TestRaises.test_raises_doesnt _______________________ - self = + self = def test_raises_doesnt(self): > raises(IOError, "int('3')") @@ -367,7 +372,7 @@ failure_demo.py:136: Failed __________________________ TestRaises.test_raise ___________________________ - self = + self = def test_raise(self): > raise ValueError("demo error") @@ -376,7 +381,7 @@ failure_demo.py:139: ValueError ________________________ TestRaises.test_tupleerror ________________________ - self = + self = def test_tupleerror(self): > a,b = [1] @@ -385,7 +390,7 @@ failure_demo.py:142: ValueError ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______ - self = + self = def test_reinterpret_fails_with_print_for_the_fun_of_it(self): l = [1,2,3] @@ -398,7 +403,7 @@ l is [1, 2, 3] ________________________ TestRaises.test_some_error ________________________ - self = + self = def test_some_error(self): > if namenotexi: @@ -426,7 +431,7 @@ <2-codegen 'abc-123' /home/hpk/p/pytest/doc/en/example/assertion/failure_demo.py:162>:2: AssertionError ____________________ TestMoreErrors.test_complex_error _____________________ - self = + self = def test_complex_error(self): def f(): @@ -450,7 +455,7 @@ failure_demo.py:5: AssertionError ___________________ TestMoreErrors.test_z1_unpack_error ____________________ - self = + self = def test_z1_unpack_error(self): l = [] @@ -460,7 +465,7 @@ failure_demo.py:179: ValueError ____________________ TestMoreErrors.test_z2_type_error _____________________ - self = + self = def test_z2_type_error(self): l = 3 @@ -470,19 +475,19 @@ failure_demo.py:183: TypeError ______________________ TestMoreErrors.test_startswith ______________________ - self = + self = def test_startswith(self): s = "123" g = "456" > assert s.startswith(g) - E assert ('456') - E + where = '123'.startswith + E assert ('456') + E + where = '123'.startswith failure_demo.py:188: AssertionError __________________ TestMoreErrors.test_startswith_nested ___________________ - self = + self = def test_startswith_nested(self): def f(): @@ -490,15 +495,15 @@ def g(): return "456" > assert f().startswith(g()) - E assert ('456') - E + where = '123'.startswith - E + where '123' = .f at 0x2adb9887e9d8>() - E + and '456' = .g at 0x2adb9887e7b8>() + E assert ('456') + E + where = '123'.startswith + E + where '123' = .f at 0x2b4436f1e950>() + E + and '456' = .g at 0x2b4436f1e840>() failure_demo.py:195: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -508,18 +513,18 @@ failure_demo.py:198: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = + self = def test_instance(self): self.x = 6*7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = .x + E + where 42 = .x failure_demo.py:202: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -529,7 +534,7 @@ failure_demo.py:205: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -540,7 +545,7 @@ failure_demo.py:210: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -554,7 +559,7 @@ failure_demo.py:221: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -571,7 +576,7 @@ failure_demo.py:227: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: @@ -589,4 +594,4 @@ E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a failure_demo.py:237: AssertionError - ======================== 42 failed in 0.29 seconds ========================= + ======================== 42 failed in 0.23 seconds ========================= diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/example/simple.txt --- a/doc/en/example/simple.txt +++ b/doc/en/example/simple.txt @@ -55,7 +55,7 @@ test_sample.py:6: AssertionError --------------------------- Captured stdout call --------------------------- first - 1 failed in 0.02 seconds + 1 failed in 0.01 seconds And now with supplying a command line option:: @@ -108,9 +108,9 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 0 items - + ============================= in 0.00 seconds ============================= .. _`excontrolskip`: @@ -152,12 +152,12 @@ $ py.test -rs # "-rs" means report details on the little 's' =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py .s ========================= short test summary info ========================== - SKIP [1] /tmp/doc-exec-229/conftest.py:9: need --runslow option to run + SKIP [1] /tmp/doc-exec-73/conftest.py:9: need --runslow option to run =================== 1 passed, 1 skipped in 0.01 seconds ==================== @@ -165,11 +165,11 @@ $ py.test --runslow =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items - + test_module.py .. - + ========================= 2 passed in 0.01 seconds ========================= Writing well integrated assertion helpers @@ -256,10 +256,10 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 project deps: mylib-1.1 collected 0 items - + ============================= in 0.00 seconds ============================= .. regendoc:wipe @@ -279,20 +279,20 @@ $ py.test -v =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 info1: did you know that ... did you? collecting ... collected 0 items - + ============================= in 0.00 seconds ============================= and nothing when run plainly:: $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 0 items - + ============================= in 0.00 seconds ============================= profiling test duration @@ -322,7 +322,7 @@ $ py.test --durations=3 =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_some_are_slow.py ... @@ -330,8 +330,8 @@ ========================= slowest 3 test durations ========================= 0.20s call test_some_are_slow.py::test_funcslow2 0.10s call test_some_are_slow.py::test_funcslow1 - 0.00s teardown test_some_are_slow.py::test_funcslow1 - ========================= 3 passed in 0.32 seconds ========================= + 0.00s setup test_some_are_slow.py::test_funcslow2 + ========================= 3 passed in 0.31 seconds ========================= incremental testing - test steps --------------------------------------------------- @@ -383,7 +383,7 @@ $ py.test -rx =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 4 items test_step.py .Fx. @@ -391,7 +391,7 @@ ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - self = + self = def test_modification(self): > assert 0 @@ -453,7 +453,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 7 items test_step.py .Fx. @@ -463,17 +463,17 @@ ================================== ERRORS ================================== _______________________ ERROR at setup of test_root ________________________ - file /tmp/doc-exec-229/b/test_error.py, line 1 + file /tmp/doc-exec-73/b/test_error.py, line 1 def test_root(db): # no db here, will error out fixture 'db' not found - available fixtures: capsys, pytestconfig, monkeypatch, tmpdir, recwarn, capfd + available fixtures: monkeypatch, pytestconfig, tmpdir, capfd, capsys, recwarn use 'py.test --fixtures [testpath]' for help on them. - /tmp/doc-exec-229/b/test_error.py:1 + /tmp/doc-exec-73/b/test_error.py:1 ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - self = + self = def test_modification(self): > assert 0 @@ -482,25 +482,25 @@ test_step.py:9: AssertionError _________________________________ test_a1 __________________________________ - db = + db = def test_a1(db): > assert 0, db # to show value - E AssertionError: + E AssertionError: E assert 0 a/test_db.py:2: AssertionError _________________________________ test_a2 __________________________________ - db = + db = def test_a2(db): > assert 0, db # to show value - E AssertionError: + E AssertionError: E assert 0 a/test_db2.py:2: AssertionError - ========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.04 seconds ========== + ========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.03 seconds ========== The two test modules in the ``a`` directory see the same ``db`` fixture instance while the one test in the sister-directory ``b`` doesn't see it. We could of course @@ -555,7 +555,7 @@ $ py.test test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py FF @@ -563,7 +563,7 @@ ================================= FAILURES ================================= ________________________________ test_fail1 ________________________________ - tmpdir = local('/tmp/pytest-22/test_fail10') + tmpdir = local('/tmp/pytest-112/test_fail10') def test_fail1(tmpdir): > assert 0 @@ -577,12 +577,12 @@ E assert 0 test_module.py:4: AssertionError - ========================= 2 failed in 0.01 seconds ========================= + ========================= 2 failed in 0.02 seconds ========================= you will have a "failures" file which contains the failing test ids:: $ cat failures - test_module.py::test_fail1 (/tmp/pytest-22/test_fail10) + test_module.py::test_fail1 (/tmp/pytest-112/test_fail10) test_module.py::test_fail2 Making test result information available in fixtures @@ -645,7 +645,7 @@ $ py.test -s test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_module.py Esetting up a test failed! test_module.py::test_setup_fails diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/example/special.txt --- a/doc/en/example/special.txt +++ b/doc/en/example/special.txt @@ -69,4 +69,4 @@ .test other .test_unit1 method called . - 4 passed in 0.05 seconds + 4 passed in 0.04 seconds diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/fixture.txt --- a/doc/en/fixture.txt +++ b/doc/en/fixture.txt @@ -76,7 +76,7 @@ $ py.test test_smtpsimple.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_smtpsimple.py F @@ -84,7 +84,7 @@ ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - smtp = + smtp = def test_ehlo(smtp): response, msg = smtp.ehlo() @@ -93,7 +93,7 @@ E TypeError: Type str doesn't support the buffer API test_smtpsimple.py:11: TypeError - ========================= 1 failed in 0.20 seconds ========================= + ========================= 1 failed in 0.28 seconds ========================= In the failure traceback we see that the test function was called with a ``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture @@ -193,7 +193,7 @@ $ py.test test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_module.py FF @@ -201,7 +201,7 @@ ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - smtp = + smtp = def test_ehlo(smtp): response = smtp.ehlo() @@ -212,7 +212,7 @@ test_module.py:5: TypeError ________________________________ test_noop _________________________________ - smtp = + smtp = def test_noop(smtp): response = smtp.noop() @@ -221,7 +221,7 @@ E assert 0 test_module.py:11: AssertionError - ========================= 2 failed in 0.17 seconds ========================= + ========================= 2 failed in 0.28 seconds ========================= You see the two ``assert 0`` failing and more importantly you can also see that the same (module-scoped) ``smtp`` object was passed into the two @@ -269,7 +269,7 @@ $ py.test -s -q --tb=no FFteardown smtp - 2 failed in 0.16 seconds + 2 failed in 0.21 seconds We see that the ``smtp`` instance is finalized after the two tests finished execution. Note that if we decorated our fixture @@ -310,7 +310,7 @@ $ py.test -s -q --tb=no FF - 2 failed in 0.16 seconds + 2 failed in 0.19 seconds Let's quickly create another test module that actually sets the server URL in its module namespace:: @@ -378,7 +378,7 @@ ================================= FAILURES ================================= __________________________ test_ehlo[merlinux.eu] __________________________ - smtp = + smtp = def test_ehlo(smtp): response = smtp.ehlo() @@ -389,7 +389,7 @@ test_module.py:5: TypeError __________________________ test_noop[merlinux.eu] __________________________ - smtp = + smtp = def test_noop(smtp): response = smtp.noop() @@ -400,7 +400,7 @@ test_module.py:11: AssertionError ________________________ test_ehlo[mail.python.org] ________________________ - smtp = + smtp = def test_ehlo(smtp): response = smtp.ehlo() @@ -410,10 +410,10 @@ test_module.py:5: TypeError -------------------------- Captured stdout setup --------------------------- - finalizing + finalizing ________________________ test_noop[mail.python.org] ________________________ - smtp = + smtp = def test_noop(smtp): response = smtp.noop() @@ -422,7 +422,7 @@ E assert 0 test_module.py:11: AssertionError - 4 failed in 6.02 seconds + 4 failed in 7.02 seconds We see that our two test functions each ran twice, against the different ``smtp`` instances. Note also, that with the ``mail.python.org`` @@ -517,13 +517,13 @@ $ py.test -v test_appsetup.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 2 items test_appsetup.py::test_smtp_exists[merlinux.eu] PASSED test_appsetup.py::test_smtp_exists[mail.python.org] PASSED - ========================= 2 passed in 5.45 seconds ========================= + ========================= 2 passed in 6.63 seconds ========================= Due to the parametrization of ``smtp`` the test will run twice with two different ``App`` instances and respective smtp servers. There is no @@ -581,7 +581,7 @@ $ py.test -v -s test_module.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4 collecting ... collected 8 items test_module.py::test_0[1] test0 1 diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/getting-started.txt --- a/doc/en/getting-started.txt +++ b/doc/en/getting-started.txt @@ -27,7 +27,7 @@ To check your installation has installed the correct version:: $ py.test --version - This is pytest version 2.6.3, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py + This is pytest version 2.6.4, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py If you get an error checkout :ref:`installation issues`. @@ -49,7 +49,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_sample.py F @@ -127,7 +127,7 @@ ================================= FAILURES ================================= ____________________________ TestClass.test_two ____________________________ - self = + self = def test_two(self): x = "hello" @@ -163,7 +163,7 @@ ================================= FAILURES ================================= _____________________________ test_needsfiles ______________________________ - tmpdir = local('/tmp/pytest-18/test_needsfiles0') + tmpdir = local('/tmp/pytest-108/test_needsfiles0') def test_needsfiles(tmpdir): print (tmpdir) @@ -172,8 +172,8 @@ test_tmpdir.py:3: AssertionError --------------------------- Captured stdout call --------------------------- - /tmp/pytest-18/test_needsfiles0 - 1 failed in 0.01 seconds + /tmp/pytest-108/test_needsfiles0 + 1 failed in 0.02 seconds Before the test runs, a unique-per-test-invocation temporary directory was created. More info at :ref:`tmpdir handling`. diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/index.txt --- a/doc/en/index.txt +++ b/doc/en/index.txt @@ -1,14 +1,10 @@ .. _features: -.. note:: - Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? April 2015 is `adopt pytest month`_! .. _`adopt pytest month`: adopt.html - - pytest: helps you write better programs ============================================= diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/parametrize.txt --- a/doc/en/parametrize.txt +++ b/doc/en/parametrize.txt @@ -53,7 +53,7 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_expectation.py ..F @@ -100,12 +100,12 @@ $ py.test =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 3 items test_expectation.py ..x - =================== 2 passed, 1 xfailed in 0.02 seconds ==================== + =================== 2 passed, 1 xfailed in 0.01 seconds ==================== The one parameter set which caused a failure previously now shows up as an "xfailed (expected to fail)" test. @@ -170,8 +170,8 @@ def test_valid_string(stringinput): > assert stringinput.isalpha() - E assert () - E + where = '!'.isalpha + E assert () + E + where = '!'.isalpha test_strings.py:3: AssertionError 1 failed in 0.01 seconds @@ -185,7 +185,7 @@ $ py.test -q -rs test_strings.py s ========================= short test summary info ========================== - SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1139: got empty parameter set, function test_valid_string at /tmp/doc-exec-180/test_strings.py:1 + SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1139: got empty parameter set, function test_valid_string at /tmp/doc-exec-23/test_strings.py:1 1 skipped in 0.01 seconds For further examples, you might want to look at :ref:`more diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/skipping.txt --- a/doc/en/skipping.txt +++ b/doc/en/skipping.txt @@ -164,7 +164,7 @@ example $ py.test -rx xfail_demo.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 7 items xfail_demo.py xxxxxxx @@ -182,7 +182,7 @@ reason: reason XFAIL xfail_demo.py::test_hello7 - ======================== 7 xfailed in 0.05 seconds ========================= + ======================== 7 xfailed in 0.04 seconds ========================= .. _`skip/xfail with parametrize`: diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/test/plugin/xdist.txt --- a/doc/en/test/plugin/xdist.txt +++ b/doc/en/test/plugin/xdist.txt @@ -159,7 +159,7 @@ each: send each test to each available environment. - load: send each test to available environment. + load: send each test to one available environment so it is run only once. (default) no: run tests inprocess, don't distribute. ``--tx=xspec`` diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/tmpdir.txt --- a/doc/en/tmpdir.txt +++ b/doc/en/tmpdir.txt @@ -29,7 +29,7 @@ $ py.test test_tmpdir.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 1 items test_tmpdir.py F @@ -37,7 +37,7 @@ ================================= FAILURES ================================= _____________________________ test_create_file _____________________________ - tmpdir = local('/tmp/pytest-19/test_create_file0') + tmpdir = local('/tmp/pytest-109/test_create_file0') def test_create_file(tmpdir): p = tmpdir.mkdir("sub").join("hello.txt") @@ -48,7 +48,7 @@ E assert 0 test_tmpdir.py:7: AssertionError - ========================= 1 failed in 0.01 seconds ========================= + ========================= 1 failed in 0.02 seconds ========================= .. _`base temporary directory`: diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e doc/en/unittest.txt --- a/doc/en/unittest.txt +++ b/doc/en/unittest.txt @@ -88,7 +88,7 @@ $ py.test test_unittest_db.py =========================== test session starts ============================ - platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 + platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.6.4 collected 2 items test_unittest_db.py FF @@ -101,7 +101,7 @@ def test_method1(self): assert hasattr(self, "db") > assert 0, self.db # fail for demo purposes - E AssertionError: .DummyDB object at 0x2b938b865208> + E AssertionError: .DummyDB object at 0x2b98cc5a2e80> E assert 0 test_unittest_db.py:9: AssertionError @@ -111,11 +111,11 @@ def test_method2(self): > assert 0, self.db # fail for demo purposes - E AssertionError: .DummyDB object at 0x2b938b865208> + E AssertionError: .DummyDB object at 0x2b98cc5a2e80> E assert 0 test_unittest_db.py:12: AssertionError - ========================= 2 failed in 0.05 seconds ========================= + ========================= 2 failed in 0.04 seconds ========================= This default pytest traceback shows that the two test methods share the same ``self.db`` instance which was our intention diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -2,14 +2,6 @@ import py import pytest -import pdb - -xfail_if_pdbpp_installed = pytest.mark.xfail( - hasattr(pdb, "__author__"), - reason="doctest/pdbpp problem: " - "https://bitbucket.org/antocuni/pdb/issue/24/" - "doctests-fail-when-pdbpp-is-installed", run=False) - class TestDoctests: @@ -162,7 +154,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_external_and_issue116(self, testdir): p = testdir.mkpydir("hello") p.join("__init__.py").write(py.code.Source(""" @@ -201,7 +192,6 @@ "*test_txtfile_failing.txt:2: DocTestFailure" ]) - @xfail_if_pdbpp_installed def test_txtfile_with_fixtures(self, testdir): p = testdir.maketxtfile(""" >>> dir = getfixture('tmpdir') @@ -211,7 +201,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_txtfile_with_usefixtures_in_ini(self, testdir): testdir.makeini(""" [pytest] @@ -232,7 +221,6 @@ reprec = testdir.inline_run(p, ) reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_with_fixtures(self, testdir): p = testdir.makepyfile(""" ''' @@ -244,7 +232,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=1) - @xfail_if_pdbpp_installed def test_doctestmodule_three_tests(self, testdir): p = testdir.makepyfile(""" ''' @@ -270,7 +257,6 @@ reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(passed=3) - @xfail_if_pdbpp_installed def test_doctestmodule_two_tests_one_fail(self, testdir): p = testdir.makepyfile(""" class MyClass: diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e testing/test_junitxml.py --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -162,7 +162,7 @@ classname="test_failure_function", name="test_fail") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="ValueError: 42") assert "ValueError" in fnode.toxml() systemout = fnode.nextSibling assert systemout.tagName == "system-out" @@ -171,6 +171,19 @@ assert systemerr.tagName == "system-err" assert "hello-stderr" in systemerr.toxml() + def test_failure_verbose_message(self, testdir): + testdir.makepyfile(""" + import sys + def test_fail(): + assert 0, "An error" + """) + + result, dom = runandparse(testdir) + node = dom.getElementsByTagName("testsuite")[0] + tnode = node.getElementsByTagName("testcase")[0] + fnode = tnode.getElementsByTagName("failure")[0] + assert_attr(fnode, message="AssertionError: An error assert 0") + def test_failure_escape(self, testdir): testdir.makepyfile(""" import pytest @@ -393,7 +406,7 @@ # classname="test_collect_error", name="myfile.xyz") fnode = tnode.getElementsByTagName("failure")[0] - assert_attr(fnode, message="test failure") + assert_attr(fnode, message="custom item runtest failed") assert "custom item runtest failed" in fnode.toxml() diff -r 6f78944be6a29393f796f7e1cd266abad32f694d -r c1c1bb35c5195a5b4c898916574cb770d22bca2e testing/test_pdb.py --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -2,8 +2,6 @@ import py import sys -from test_doctest import xfail_if_pdbpp_installed - class TestPDB: def pytest_funcarg__pdblist(self, request): @@ -189,7 +187,6 @@ if child.isalive(): child.wait() - @xfail_if_pdbpp_installed def test_pdb_interaction_doctest(self, testdir): p1 = testdir.makepyfile(""" import pytest Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 20:45:13 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 19:45:13 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 384 Message-ID: <20150222194513.10168.63113@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/384 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3880:c1c1bb35c519 Author : Ronny Pfannschmidt Branch : flake8-clean Message: merge from default -------------- next part -------------- An HTML attachment was scrubbed... URL: From issues-reply at bitbucket.org Sun Feb 22 21:08:28 2015 From: issues-reply at bitbucket.org (Ronny Pfannschmidt) Date: Sun, 22 Feb 2015 20:08:28 -0000 Subject: [Pytest-commit] Issue #686: pytester confcut dir os not set to basetmp (hpk42/pytest) Message-ID: <20150222200828.17292.6868@app03.ash-private.bitbucket.org> New issue 686: pytester confcut dir os not set to basetmp https://bitbucket.org/hpk42/pytest/issue/686/pytester-confcut-dir-os-not-set-to-basetmp Ronny Pfannschmidt: had a file named conftest in /tmp after a download, the world broke because it was python2 only Responsible: RonnyPfannschmidt From commits-noreply at bitbucket.org Sun Feb 22 21:12:16 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sun, 22 Feb 2015 20:12:16 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: close junit-verbose-failures Message-ID: <20150222201216.9150.14111@app06.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/9db4036d5f46/ Changeset: 9db4036d5f46 Branch: junit-verbose-failures User: RonnyPfannschmidt Date: 2015-02-22 20:12:00+00:00 Summary: close junit-verbose-failures Affected #: 0 files Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sun Feb 22 21:20:16 2015 From: builds at drone.io (Drone.io Build) Date: Sun, 22 Feb 2015 20:20:16 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 385 Message-ID: <20150222202016.109567.72098@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/385 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3836:9db4036d5f46 Author : Ronny Pfannschmidt Branch : junit-verbose-failures Message: close junit-verbose-failures -------------- next part -------------- An HTML attachment was scrubbed... URL: From issues-reply at bitbucket.org Mon Feb 23 11:58:56 2015 From: issues-reply at bitbucket.org (Thomas Tanner) Date: Mon, 23 Feb 2015 10:58:56 -0000 Subject: [Pytest-commit] Issue #687: fixture finalization is delayed (hpk42/pytest) Message-ID: <20150223105856.29287.79325@app09.ash-private.bitbucket.org> New issue 687: fixture finalization is delayed https://bitbucket.org/hpk42/pytest/issue/687/fixture-finalization-is-delayed Thomas Tanner: According to the documentation http://pytest.org/latest/fixture.html#fixture-finalization-executing-teardown-code "The fin function will execute when the last test using the fixture in the module has finished execution." Either the documentation is wrong, misleading or there is a bug in pytest. Example: ``` #!python from pytest import fixture @fixture(scope='session') def fix1(request): print 'fix1' def fin(): print '-fix1' request.addfinalizer(fin) return 'fix1' @fixture(scope='session') def fix2(request): print 'fix2' def fin(): print '-fix2' request.addfinalizer(fin) return 'fix2' def test_f1(fix1): print 'f1',fix1 def test_f2(fix2): print 'f2',fix2 ``` results in ``` #! test.py::test_f1 fix1 f1 fix1 PASSED test.py::test_f2 fix2 f2 fix2 PASSED-fix2 -fix1 ``` as you can see, fin of fix1 is called not immediately after the last test depending on it (f1), but after all other tests (f2) and fix2's fin. Just in case pytest won't guarantee finalization of a fixture after all its dependencies have been executed: what would be the best way to ensure mutually-exclusive (session) fixtures are finalized before the next one is setup? From commits-noreply at bitbucket.org Mon Feb 23 15:06:53 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 23 Feb 2015 14:06:53 -0000 Subject: [Pytest-commit] commit/tox: hpk42: Merged in suor/tox/generative-example (pull request #135) Message-ID: <20150223140653.17884.34370@app03.ash-private.bitbucket.org> 1 new commit in tox: https://bitbucket.org/hpk42/tox/commits/a2278870aa11/ Changeset: a2278870aa11 User: hpk42 Date: 2015-02-23 14:06:50+00:00 Summary: Merged in suor/tox/generative-example (pull request #135) Add generative config example Affected #: 2 files diff -r 0a85dfb460906c3434651b594b591d0426530744 -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -261,7 +261,7 @@ Do not install the current package. This can be used when you need the virtualenv management but do not want to install the current package into that environment. - + **default**: ``False`` @@ -449,6 +449,8 @@ Let's go through this step by step. +.. _generative-envlist: + Generative envlist +++++++++++++++++++++++ @@ -482,6 +484,8 @@ flake +.. _factors: + Factors and factor-conditional settings ++++++++++++++++++++++++++++++++++++++++ diff -r 0a85dfb460906c3434651b594b591d0426530744 -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 doc/example/basic.txt --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -74,7 +74,7 @@ (experimental) If you have a ``requirements.txt`` file you can add it to your ``deps`` variable like this:: - deps = -rrequirements.txt + deps = -rrequirements.txt All installation commands are executed using ``{toxinidir}`` (the directory where ``tox.ini`` resides) as the current @@ -260,3 +260,20 @@ By using the ``-`` prefix, similar to a ``make`` recipe line, you can ignore the exit code for that command. + +Compressing dependency matrix +----------------------------- + +If you have a large matrix of dependencies, python versions and/or environments you can +use :ref:`generative-envlist` and :ref:`conditional settings ` to express that in a concise form:: + + [tox] + envlist = py{26,27,33}-django{15,16}-{sqlite,mysql} + + [testenv] + deps = + django15: Django>=1.5,<1.6 + django16: Django>=1.6,<1.7 + py33-mysql: PyMySQL ; use if both py33 and mysql are in an env name + py26,py27: urllib3 ; use if any of py26 or py27 are in an env name + py{26,27}-sqlite: mock ; mocking sqlite in python 2.x Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 23 15:06:54 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 23 Feb 2015 14:06:54 -0000 Subject: [Pytest-commit] commit/tox: 2 new changesets Message-ID: <20150223140654.13000.5483@app08.ash-private.bitbucket.org> 2 new commits in tox: https://bitbucket.org/hpk42/tox/commits/588ddd566df5/ Changeset: 588ddd566df5 Branch: generative-example User: suor Date: 2015-02-23 13:15:37+00:00 Summary: Add generative config example Affected #: 2 files diff -r 0a85dfb460906c3434651b594b591d0426530744 -r 588ddd566df53f96d65afb9c20c75fb2dcf96dc6 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -261,7 +261,7 @@ Do not install the current package. This can be used when you need the virtualenv management but do not want to install the current package into that environment. - + **default**: ``False`` @@ -449,6 +449,8 @@ Let's go through this step by step. +.. _generative-envlist: + Generative envlist +++++++++++++++++++++++ @@ -482,6 +484,8 @@ flake +.. _factors: + Factors and factor-conditional settings ++++++++++++++++++++++++++++++++++++++++ diff -r 0a85dfb460906c3434651b594b591d0426530744 -r 588ddd566df53f96d65afb9c20c75fb2dcf96dc6 doc/example/basic.txt --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -74,7 +74,7 @@ (experimental) If you have a ``requirements.txt`` file you can add it to your ``deps`` variable like this:: - deps = -rrequirements.txt + deps = -rrequirements.txt All installation commands are executed using ``{toxinidir}`` (the directory where ``tox.ini`` resides) as the current @@ -260,3 +260,20 @@ By using the ``-`` prefix, similar to a ``make`` recipe line, you can ignore the exit code for that command. + +Compressing dependency matrix +----------------------------- + +If you have a large matrix of dependencies, python versions and/or environments you can +use :ref:`generative-envlist` and :ref:`conditional settings ` to express that in a concise form:: + + [tox] + envlist = py{26,27,33}-django{15,16}-{sqlite,mysql} + + [testenv] + deps = + django15: Django>=1.5,<1.6 + django16: Django>=1.6,<1.7 + py33-mysql: PyMySQL ; use if both py33 and mysql are in an env name + py26,py27: urllib3 ; use if any of py26 or py27 are in an env name + py{26,27}-sqlite: mock ; mocking sqlite in python 2.x https://bitbucket.org/hpk42/tox/commits/a2278870aa11/ Changeset: a2278870aa11 User: hpk42 Date: 2015-02-23 14:06:50+00:00 Summary: Merged in suor/tox/generative-example (pull request #135) Add generative config example Affected #: 2 files diff -r 0a85dfb460906c3434651b594b591d0426530744 -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 doc/config.txt --- a/doc/config.txt +++ b/doc/config.txt @@ -261,7 +261,7 @@ Do not install the current package. This can be used when you need the virtualenv management but do not want to install the current package into that environment. - + **default**: ``False`` @@ -449,6 +449,8 @@ Let's go through this step by step. +.. _generative-envlist: + Generative envlist +++++++++++++++++++++++ @@ -482,6 +484,8 @@ flake +.. _factors: + Factors and factor-conditional settings ++++++++++++++++++++++++++++++++++++++++ diff -r 0a85dfb460906c3434651b594b591d0426530744 -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 doc/example/basic.txt --- a/doc/example/basic.txt +++ b/doc/example/basic.txt @@ -74,7 +74,7 @@ (experimental) If you have a ``requirements.txt`` file you can add it to your ``deps`` variable like this:: - deps = -rrequirements.txt + deps = -rrequirements.txt All installation commands are executed using ``{toxinidir}`` (the directory where ``tox.ini`` resides) as the current @@ -260,3 +260,20 @@ By using the ``-`` prefix, similar to a ``make`` recipe line, you can ignore the exit code for that command. + +Compressing dependency matrix +----------------------------- + +If you have a large matrix of dependencies, python versions and/or environments you can +use :ref:`generative-envlist` and :ref:`conditional settings ` to express that in a concise form:: + + [tox] + envlist = py{26,27,33}-django{15,16}-{sqlite,mysql} + + [testenv] + deps = + django15: Django>=1.5,<1.6 + django16: Django>=1.6,<1.7 + py33-mysql: PyMySQL ; use if both py33 and mysql are in an env name + py26,py27: urllib3 ; use if any of py26 or py27 are in an env name + py{26,27}-sqlite: mock ; mocking sqlite in python 2.x Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Mon Feb 23 16:15:28 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Mon, 23 Feb 2015 15:15:28 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: change "install" targets to use pytest-dev user so that Brianna, Ronny, me Message-ID: <20150223151528.11706.50588@app03.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/6104c7ea0dcc/ Changeset: 6104c7ea0dcc User: hpk42 Date: 2015-02-23 15:14:54+00:00 Summary: change "install" targets to use pytest-dev user so that Brianna, Ronny, me and others can push to pytest.org Affected #: 1 file diff -r 4e32db33cb496587858c04818c48adc1112d86d8 -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 doc/en/Makefile --- a/doc/en/Makefile +++ b/doc/en/Makefile @@ -12,7 +12,6 @@ PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -SITETARGET=latest .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest @@ -43,11 +42,15 @@ clean: -rm -rf $(BUILDDIR)/* +SITETARGET=dev + install: html - rsync -avz _build/html/ pytest.org:/www/pytest.org/$(SITETARGET) + # for access talk to someone with login rights to + # pytest-dev at pytest.org to add your ssh key + rsync -avz _build/html/ pytest-dev at pytest.org:/www/pytest.org/$(SITETARGET) installpdf: latexpdf - @scp $(BUILDDIR)/latex/pytest.pdf pytest.org:/www/pytest.org/$(SITETARGET) + @scp $(BUILDDIR)/latex/pytest.pdf pytest-dev at pytest.org:/www/pytest.org/$(SITETARGET) installall: clean install installpdf @echo "done" Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From issues-reply at bitbucket.org Tue Feb 24 14:42:52 2015 From: issues-reply at bitbucket.org (Daniel Hahler) Date: Tue, 24 Feb 2015 13:42:52 -0000 Subject: [Pytest-commit] Issue #221: UnicodeEncodeError when trying to install file with special symbols (hpk42/tox) Message-ID: <20150224134252.5660.13893@app10.ash-private.bitbucket.org> New issue 221: UnicodeEncodeError when trying to install file with special symbols https://bitbucket.org/hpk42/tox/issue/221/unicodeencodeerror-when-trying-to-install Daniel Hahler: Installing Django master fails via tox / pip with an UnicodeEncodeError for a file with a special file name. The file has been added in https://github.com/django/django/commit/bd059e3f8c6311dcaf8afe5e29ef373f7f84cf26, and the issue is reported for pip at: https://github.com/pypa/pip/issues/1698#issuecomment-75755252. TEST CASE: ``` #!sh git clone https://github.com/pytest-dev/pytest-django cd pytest-django tox -e python2.7-master-sqlite_file ``` The error is: ``` GLOB sdist-make: /tmp/pytest-django/setup.py python2.7-master-sqlite_file create: /tmp/pytest-django/.tox/python2.7-master-sqlite_file python2.7-master-sqlite_file installdeps: pytest==2.6.4, pytest-xdist==1.11, https://github.com/django/django/archive/master.zip, django-configurations==0.8, south==1.0.2 ERROR: invocation failed (exit code 2), logfile: /tmp/pytest-django/.tox/python2.7-master-sqlite_file/log/python2.7-master-sqlite_file-1.log ERROR: actionid=python2.7-master-sqlite_file msg=getenv cmdargs=[local('/tmp/pytest-django/.tox/python2.7-master-sqlite_file/bin/pip'), 'install', '--pre', 'pytest==2.6.4', 'pytest-xdist==1.11', 'https://github.com/django/django/archive/master.zip', 'django-configurations==0.8', 'south==1.0.2'] env={...} DEPRECATION: --download-cache has been deprecated and will be removed in the future. Pip now automatically uses and configures its cache. Collecting https://github.com/django/django/archive/master.zip Downloading https://github.com/django/django/archive/master.zip (11.4MB) Exception: Traceback (most recent call last): File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/basecommand.py", line 232, in main status = self.run(options, args) File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/commands/install.py", line 339, in run requirement_set.prepare_files(finder) File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/req/req_set.py", line 355, in prepare_files do_download, session=self.session, File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/download.py", line 782, in unpack_url session, File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/download.py", line 671, in unpack_http_url unpack_file(from_path, location, content_type, link) File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/utils/__init__.py", line 648, in unpack_file flatten=not filename.endswith('.whl') File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/utils/__init__.py", line 528, in unzip_file leading = has_leading_dir(zip.namelist()) and flatten File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/utils/__init__.py", line 253, in has_leading_dir prefix, rest = split_leading_dir(path) File "/tmp/pytest-django/.tox/python2.7-master-sqlite_file/lib/python2.7/site-packages/pip/utils/__init__.py", line 237, in split_leading_dir path = str(path) UnicodeEncodeError: 'ascii' codec can't encode character u'\u2297' in position 60: ordinal not in range(128) ERROR: could not install deps [pytest==2.6.4, pytest-xdist==1.11, https://github.com/django/django/archive/master.zip, django-configurations==0.8, south==1.0.2]; v = InvocationError('/tmp/pytest-django/.tox/python2.7-master-sqlite_file/bin/pip install --pre pytest==2.6.4 pytest-xdist==1.11 https://github.com/django/django/archive/master.zip django-configurations==0.8 south==1.0.2 (see /tmp/pytest-django/.tox/python2.7-master-sqlite_file/log/python2.7-master-sqlite_file-1.log)', 2) __________________________________________________________ summary ___________________________________________________________ ERROR: python2.7-master-sqlite_file: could not install deps [pytest==2.6.4, pytest-xdist==1.11, https://github.com/django/django/archive/master.zip, django-configurations==0.8, south==1.0.2]; v = InvocationError('/tmp/pytest-django/.tox/python2.7-master-sqlite_file/bin/pip install --pre pytest==2.6.4 pytest-xdist==1.11 https://github.com/django/django/archive/master.zip django-configurations==0.8 south==1.0.2 (see /tmp/pytest-django/.tox/python2.7-master-sqlite_file/log/python2.7-master-sqlite_file-1.log)', 2) ``` From commits-noreply at bitbucket.org Tue Feb 24 16:51:23 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Tue, 24 Feb 2015 15:51:23 -0000 Subject: [Pytest-commit] commit/tox: 2 new changesets Message-ID: <20150224155123.24570.53614@app14.ash-private.bitbucket.org> 2 new commits in tox: https://bitbucket.org/hpk42/tox/commits/ad64513cf6bf/ Changeset: ad64513cf6bf User: hpk42 Date: 2015-02-24 15:45:14+00:00 Summary: 1.9.0 Affected #: 6 files diff -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 -r ad64513cf6bf0ef99a4a11678aa3260d8078976f CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -1.9.0.dev +1.9.0 ----------- - fix issue193: Remove ``--pre`` from the default ``install_command``; by diff -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 -r ad64513cf6bf0ef99a4a11678aa3260d8078976f doc/announce/release-1.9.txt --- /dev/null +++ b/doc/announce/release-1.9.txt @@ -0,0 +1,66 @@ +tox-1.9: refinements, fixes (+detox-0.9.4) +========================================== + +tox-1.9 was released to pypi, a maintenance release with mostly +backward-compatible enhancements and fixes. However, tox now defaults +to pip-installing only non-development releases and you have to set "pip_pre = +True" in your testenv section to have it install development ("pre") releases. + +In addition, there is a new detox-0.9.4 out which allow to run tox test +environments in parallel and fixes a compat problem with eventlet. + +Thanks to Alexander Schepanosvki, Florian Schulze and others for the +contributed fixes and improvements. + +More documentation about tox in general: + + http://tox.testrun.org/ + +Installation: + + pip install -U tox + +code hosting and issue tracking on bitbucket: + + https://bitbucket.org/hpk42/tox + +What is tox? +---------------- + +tox standardizes and automates tedious test activities driven from a +simple ``tox.ini`` file, including: + +* creation and management of different virtualenv environments + with different Python interpreters +* packaging and installing your package into each of them +* running your test tool of choice, be it nose, py.test or unittest2 or other tools such as "sphinx" doc checks +* testing dev packages against each other without needing to upload to PyPI + +best, +Holger Krekel, merlinux GmbH + + +1.9.0 +----------- + +- fix issue193: Remove ``--pre`` from the default ``install_command``; by + default tox will now only install final releases from PyPI for unpinned + dependencies. Use ``pip_pre = true`` in a testenv or the ``--pre`` + command-line option to restore the previous behavior. + +- fix issue199: fill resultlog structure ahead of virtualenv creation + +- refine determination if we run from Jenkins, thanks Borge Lanes. + +- echo output to stdout when ``--report-json`` is used + +- fix issue11: add a ``skip_install`` per-testenv setting which + prevents the installation of a package. Thanks Julian Krause. + +- fix issue124: ignore command exit codes; when a command has a "-" prefix, + tox will ignore the exit code of that command + +- fix issue198: fix broken envlist settings, e.g. {py26,py27}{-lint,} + +- fix issue191: lessen factor-use checks + diff -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 -r ad64513cf6bf0ef99a4a11678aa3260d8078976f doc/conf.py --- a/doc/conf.py +++ b/doc/conf.py @@ -48,8 +48,8 @@ # built documents. # # The short X.Y version. -release = "1.8" -version = "1.8.1" +release = "1.9" +version = "1.9.0" # The full version, including alpha/beta/rc tags. # The language for content autogenerated by Sphinx. Refer to documentation diff -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 -r ad64513cf6bf0ef99a4a11678aa3260d8078976f setup.py --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ description='virtualenv-based automation of test activities', long_description=open("README.rst").read(), url='http://tox.testrun.org/', - version='1.8.2.dev1', + version='1.9.0', license='http://opensource.org/licenses/MIT', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], author='holger krekel', diff -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 -r ad64513cf6bf0ef99a4a11678aa3260d8078976f tox.ini --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist=py27,py26,py34,py33,py32,pypy,flakes +envlist=py27,py26,py34,py33,pypy,flakes [testenv:X] commands=echo {posargs} @@ -14,7 +14,7 @@ deps=sphinx {[testenv]deps} commands= - py.test -v \ + py.test -v --junitxml={envlogdir}/junit-{envname}.xml \ check_sphinx.py {posargs} @@ -22,9 +22,6 @@ deps = pytest-flakes>=0.2 commands = py.test --flakes -m flakes tox tests -[testenv:py25] -setenv= PIP_INSECURE=1 - [pytest] rsyncdirs=tests tox addopts = -rsxXf diff -r a2278870aa11f63112ec06f3adc9e0bea36b9a90 -r ad64513cf6bf0ef99a4a11678aa3260d8078976f tox/__init__.py --- a/tox/__init__.py +++ b/tox/__init__.py @@ -1,5 +1,5 @@ # -__version__ = '1.8.2.dev1' +__version__ = '1.9.0' class exception: class Error(Exception): https://bitbucket.org/hpk42/tox/commits/69f9be62ef38/ Changeset: 69f9be62ef38 User: hpk42 Date: 2015-02-24 15:46:42+00:00 Summary: Added tag 1.9.0 for changeset ad64513cf6bf Affected #: 1 file diff -r ad64513cf6bf0ef99a4a11678aa3260d8078976f -r 69f9be62ef38ef3dca9a932d79f2df85c834258a .hgtags --- a/.hgtags +++ b/.hgtags @@ -20,3 +20,4 @@ e319e464470a5885505ab3e1da1a3a7abe5f86e2 1.7.2 b7374e501bde055c5c2b572e6512d22e10f60088 1.8.0 2aa9b587d12ae4b325cb4d5a9a801a222ffc328c 1.8.1 +ad64513cf6bf0ef99a4a11678aa3260d8078976f 1.9.0 Repository URL: https://bitbucket.org/hpk42/tox/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From issues-reply at bitbucket.org Tue Feb 24 22:39:47 2015 From: issues-reply at bitbucket.org (Barry Warsaw) Date: Tue, 24 Feb 2015 21:39:47 -0000 Subject: [Pytest-commit] Issue #222: setenv with generated environments require unwanted settings (hpk42/tox) Message-ID: <20150224213947.27120.46894@app10.ash-private.bitbucket.org> New issue 222: setenv with generated environments require unwanted settings https://bitbucket.org/hpk42/tox/issue/222/setenv-with-generated-environments-require Barry Warsaw: Here is a my tox.ini file: ``` [tox] envlist = py27,py34,coverage-{py27,py34},fast-{py27,py34} recreate = True [coverage] rcfile = {toxinidir}/{envname}.ini rc = --rcfile={[coverage]rcfile} dir = --directory={envname} setenv = coverage: COVERAGE_PROCESS_START={[coverage]rcfile} coverage: COVERAGE_OPTIONS="-p" coverage: COVERAGE_FILE={toxinidir}/.coverage [testenv] commands = py27,py34: python -m nose2 -v coverage: python /usr/bin/python3-coverage run {[coverage]rc} -m nose2 -v coverage: python3-coverage combine {[coverage]rc} coverage: python3-coverage html {[coverage]rc} {[coverage]dir} sitepackages = True usedevelop = True whitelist_externals = python3-coverage setenv = fast: SKIP_SLOW_TESTS=1 py34,py27: SKIP_SLOW_TESTS=0 ``` Then: ``` % tox -l py27 py34 coverage-py27 coverage-py34 fast-py27 fast-py34 ``` However, if the line ```py34,py27: SKIP_SLOW_TESTS=0``` is omitted, then I get a traceback: ``` % tox -l Traceback (most recent call last): File "/usr/bin/tox", line 9, in load_entry_point('tox==1.8.0', 'console_scripts', 'tox')() File "/usr/lib/python3/dist-packages/tox/_cmdline.py", line 25, in main config = parseconfig(args, 'tox') File "/usr/lib/python3/dist-packages/tox/_config.py", line 42, in parseconfig parseini(config, inipath) File "/usr/lib/python3/dist-packages/tox/_config.py", line 296, in __init__ self._makeenvconfig(name, section, reader._subs, config) File "/usr/lib/python3/dist-packages/tox/_config.py", line 354, in _makeenvconfig setenv.update(reader.getdict(section, 'setenv')) File "/usr/lib/python3/dist-packages/tox/_config.py", line 529, in getdict name, rest = line.split('=', 1) ValueError: need more than 1 value to unpack ``` From issues-reply at bitbucket.org Tue Feb 24 22:46:52 2015 From: issues-reply at bitbucket.org (Barry Warsaw) Date: Tue, 24 Feb 2015 21:46:52 -0000 Subject: [Pytest-commit] Issue #223: Please add a [tox]default_envlist setting (hpk42/tox) Message-ID: <20150224214652.20956.70972@app05.ash-private.bitbucket.org> New issue 223: Please add a [tox]default_envlist setting https://bitbucket.org/hpk42/tox/issue/223/please-add-a-tox-default_envlist-setting Barry Warsaw: Maybe I'm missing something obvious, but I think I want a way to both define a bunch of environments, including some generated ones, but I also want tox-with-no-args to only run a few of them by default. For example: ``` [tox] envlist = py27,py34,coverage-{py27,py34},fast-{py27,py34} ``` Now, if I run just ```tox`` it will run all these tests. But I want to make it easy for my users and CI system to only run a few of those environments by default. So I'd like for ```tox``` with no arguments to e.g., only run fast-py27 and fast-py34. Then, if they say something like ```tox --all``` it would run all environments. One thought would be to add something like: ``` [tox] envlist = py27,py34,coverage-{py27,py34},fast-{py27,py34} default_envlist = fast-{py27,py34} ``` and that would be the no-arg set of environments that get run. ```--all``` would ignore default_envlist. I guess this can work with an explicit -e option and the current default to run all environments, but it's a little less convenient because the set of all environments could change and then I'd have to retool my CI or update my README, etc. Or is this a dumb idea? ;) From issues-reply at bitbucket.org Wed Feb 25 16:21:24 2015 From: issues-reply at bitbucket.org (mcarans) Date: Wed, 25 Feb 2015 15:21:24 -0000 Subject: [Pytest-commit] Issue #224: Generate .whl in .tox/dist (hpk42/tox) Message-ID: <20150225152124.27300.42927@app12.ash-private.bitbucket.org> New issue 224: Generate .whl in .tox/dist https://bitbucket.org/hpk42/tox/issue/224/generate-whl-in-tox-dist mcarans: It would be great to have the option of generating a whl file in .tox/dist when tox builds the package Responsible: hpk42 From issues-reply at bitbucket.org Thu Feb 26 17:11:12 2015 From: issues-reply at bitbucket.org (Ronny Pfannschmidt) Date: Thu, 26 Feb 2015 16:11:12 -0000 Subject: [Pytest-commit] Issue #688: document pytest-runner as setup.py integration (hpk42/pytest) Message-ID: <20150226161112.6527.36976@app04.ash-private.bitbucket.org> New issue 688: document pytest-runner as setup.py integration https://bitbucket.org/hpk42/pytest/issue/688/document-pytest-runner-as-setuppy Ronny Pfannschmidt: https://bitbucket.org/jaraco/pytest-runner Responsible: RonnyPfannschmidt From commits-noreply at bitbucket.org Thu Feb 26 18:51:00 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 26 Feb 2015 17:51:00 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: close branch before making a new version Message-ID: <20150226175100.18648.81688@app10.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/dde147c0de32/ Changeset: dde147c0de32 Branch: copy-in-cache User: RonnyPfannschmidt Date: 2015-02-26 17:50:32+00:00 Summary: close branch before making a new version Affected #: 0 files Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Thu Feb 26 19:00:31 2015 From: builds at drone.io (Drone.io Build) Date: Thu, 26 Feb 2015 18:00:31 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 386 Message-ID: <20150226180018.39434.9973@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/386 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3856:dde147c0de32 Author : Ronny Pfannschmidt Branch : copy-in-cache Message: close branch before making a new version -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Thu Feb 26 21:56:55 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 26 Feb 2015 20:56:55 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: fix issue616 - conftest visibility fixes. This is achieved by Message-ID: <20150226205655.30623.21082@app05.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/327ead9d7e9b/ Changeset: 327ead9d7e9b Branch: issue616 User: hpk42 Date: 2015-02-26 20:56:44+00:00 Summary: fix issue616 - conftest visibility fixes. This is achieved by refactoring how nodeid's are constructed. They now are always relative to the "common rootdir" of a test run which is determined by finding a common ancestor of all testrun arguments. Affected #: 13 files diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,20 @@ 2.7.0.dev (compared to 2.6.4) ----------------------------- +- fix issue616: conftest.py files and their contained fixutres are now + properly considered for visibility, independently from the exact + current working directory and test arguments that are used. + Many thanks to Eric Siegerman and his PR235 which contains + systematic tests for conftest visibility and now passes. + This change also introduces the concept of a ``rootdir`` which + is printed as a new pytest header and documented in the pytest + customize web page. + +- change reporting of "diverted" tests, i.e. tests that are collected + in one file but actually come from another (e.g. when tests in a test class + come from a base class in a different file). We now show the nodeid + and indicate via a postfix the other file. + - add ability to set command line options by environment variable PYTEST_ADDOPTS. - fix issue655: work around different ways that cause python2/3 diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -657,6 +657,12 @@ sys.stderr.write("INTERNALERROR> %s\n" %line) sys.stderr.flush() + def cwd_relative_nodeid(self, nodeid): + # nodeid's are relative to the rootpath, compute relative to cwd + if self.invocation_dir != self.rootdir: + fullpath = self.rootdir.join(nodeid) + nodeid = self.invocation_dir.bestrelpath(fullpath) + return nodeid @classmethod def fromdictargs(cls, option_dict, args): @@ -691,14 +697,9 @@ def _initini(self, args): parsed_args = self._parser.parse_known_args(args) - if parsed_args.inifilename: - iniconfig = py.iniconfig.IniConfig(parsed_args.inifilename) - if 'pytest' in iniconfig.sections: - self.inicfg = iniconfig['pytest'] - else: - self.inicfg = {} - else: - self.inicfg = getcfg(args, ["pytest.ini", "tox.ini", "setup.cfg"]) + r = determine_setup(parsed_args.inifilename, parsed_args.file_or_dir) + self.rootdir, self.inifile, self.inicfg = r + self.invocation_dir = py.path.local() self._parser.addini('addopts', 'extra command line options', 'args') self._parser.addini('minversion', 'minimally required pytest version') @@ -859,8 +860,58 @@ if exists(p): iniconfig = py.iniconfig.IniConfig(p) if 'pytest' in iniconfig.sections: - return iniconfig['pytest'] - return {} + return base, p, iniconfig['pytest'] + elif inibasename == "pytest.ini": + # allowed to be empty + return base, p, {} + return None, None, None + + +def get_common_ancestor(args): + # args are what we get after early command line parsing (usually + # strings, but can be py.path.local objects as well) + common_ancestor = None + for arg in args: + if str(arg)[0] == "-": + continue + p = py.path.local(arg) + if common_ancestor is None: + common_ancestor = p + else: + if p.relto(common_ancestor) or p == common_ancestor: + continue + elif common_ancestor.relto(p): + common_ancestor = p + else: + shared = p.common(common_ancestor) + if shared is not None: + common_ancestor = shared + if common_ancestor is None: + common_ancestor = py.path.local() + elif not common_ancestor.isdir(): + common_ancestor = common_ancestor.dirpath() + return common_ancestor + + +def determine_setup(inifile, args): + if inifile: + iniconfig = py.iniconfig.IniConfig(inifile) + try: + inicfg = iniconfig["pytest"] + except KeyError: + inicfg = None + rootdir = get_common_ancestor(args) + else: + ancestor = get_common_ancestor(args) + rootdir, inifile, inicfg = getcfg( + [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"]) + if rootdir is None: + for rootdir in ancestor.parts(reverse=True): + if rootdir.join("setup.py").exists(): + break + else: + rootdir = ancestor + return rootdir, inifile, inicfg or {} def setns(obj, dic): diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 _pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -457,9 +457,7 @@ self.fspath = fspath def _makeid(self): - if self == self.session: - return "." - relpath = self.session.fspath.bestrelpath(self.fspath) + relpath = self.fspath.relto(self.config.rootdir) if os.sep != "/": relpath = relpath.replace(os.sep, "/") return relpath @@ -510,7 +508,7 @@ __module__ = 'builtins' # for py3 def __init__(self, config): - FSCollector.__init__(self, py.path.local(), parent=None, + FSCollector.__init__(self, config.rootdir, parent=None, config=config, session=self) self.config.pluginmanager.register(self, name="session", prepend=True) self._testsfailed = 0 @@ -520,6 +518,9 @@ self.startdir = py.path.local() self._fs2hookproxy = {} + def _makeid(self): + return "" + def pytest_collectstart(self): if self.shouldstop: raise self.Interrupted(self.shouldstop) @@ -663,7 +664,7 @@ arg = self._tryconvertpyarg(arg) parts = str(arg).split("::") relpath = parts[0].replace("/", os.sep) - path = self.fspath.join(relpath, abs=True) + path = self.config.invocation_dir.join(relpath, abs=True) if not path.check(): if self.config.option.pyargs: msg = "file or package not found: " diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 _pytest/pytester.py --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -306,9 +306,8 @@ session = Session(config) assert '::' not in str(arg) p = py.path.local(arg) - x = session.fspath.bestrelpath(p) config.hook.pytest_sessionstart(session=session) - res = session.perform_collect([x], genitems=False)[0] + res = session.perform_collect([str(p)], genitems=False)[0] config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) return res @@ -395,8 +394,7 @@ def parseconfigure(self, *args): config = self.parseconfig(*args) config.do_configure() - self.request.addfinalizer(lambda: - config.do_unconfigure()) + self.request.addfinalizer(config.do_unconfigure) return config def getitem(self, source, funcname="test_func"): diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1653,11 +1653,9 @@ # what fixtures are visible for particular tests (as denoted # by their test id) if p.basename.startswith("conftest.py"): - nodeid = self.session.fspath.bestrelpath(p.dirpath()) + nodeid = p.dirpath().relto(self.config.rootdir) if p.sep != "/": nodeid = nodeid.replace(p.sep, "/") - if nodeid == ".": - nodeid = "" self.parsefactories(plugin, nodeid) self._seenplugins.add(plugin) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 _pytest/skipping.py --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -218,14 +218,14 @@ failed = terminalreporter.stats.get(stat) if failed: for rep in failed: - pos = rep.nodeid - lines.append(format %(pos, )) + pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid) + lines.append(format %(pos,)) def show_xfailed(terminalreporter, lines): xfailed = terminalreporter.stats.get("xfailed") if xfailed: for rep in xfailed: - pos = rep.nodeid + pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid) reason = rep.wasxfail lines.append("XFAIL %s" % (pos,)) if reason: @@ -235,7 +235,7 @@ xpassed = terminalreporter.stats.get("xpassed") if xpassed: for rep in xpassed: - pos = rep.nodeid + pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid) reason = rep.wasxfail lines.append("XPASS %s %s" %(pos, reason)) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 _pytest/terminal.py --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -95,7 +95,7 @@ self._numcollected = 0 self.stats = {} - self.startdir = self.curdir = py.path.local() + self.startdir = py.path.local() if file is None: file = sys.stdout self._tw = self.writer = py.io.TerminalWriter(file) @@ -111,12 +111,12 @@ char = {'xfailed': 'x', 'skipped': 's'}.get(char, char) return char in self.reportchars - def write_fspath_result(self, fspath, res): + def write_fspath_result(self, nodeid, res): + fspath = self.config.rootdir.join(nodeid.split("::")[0]) if fspath != self.currentfspath: self.currentfspath = fspath - #fspath = self.startdir.bestrelpath(fspath) + fspath = self.startdir.bestrelpath(fspath) self._tw.line() - #relpath = self.startdir.bestrelpath(fspath) self._tw.write(fspath + " ") self._tw.write(res) @@ -182,12 +182,12 @@ def pytest_runtest_logstart(self, nodeid, location): # ensure that the path is printed before the # 1st test of a module starts running - fspath = nodeid.split("::")[0] if self.showlongtestinfo: - line = self._locationline(fspath, *location) + line = self._locationline(nodeid, *location) self.write_ensure_prefix(line, "") elif self.showfspath: - self.write_fspath_result(fspath, "") + fsid = nodeid.split("::")[0] + self.write_fspath_result(fsid, "") def pytest_runtest_logreport(self, report): rep = report @@ -200,7 +200,7 @@ return if self.verbosity <= 0: if not hasattr(rep, 'node') and self.showfspath: - self.write_fspath_result(rep.fspath, letter) + self.write_fspath_result(rep.nodeid, letter) else: self._tw.write(letter) else: @@ -213,7 +213,7 @@ markup = {'red':True} elif rep.skipped: markup = {'yellow':True} - line = self._locationline(str(rep.fspath), *rep.location) + line = self._locationline(rep.nodeid, *rep.location) if not hasattr(rep, 'node'): self.write_ensure_prefix(line, word, **markup) #self._tw.write(word, **markup) @@ -237,7 +237,7 @@ items = [x for x in report.result if isinstance(x, pytest.Item)] self._numcollected += len(items) if self.hasmarkup: - #self.write_fspath_result(report.fspath, 'E') + #self.write_fspath_result(report.nodeid, 'E') self.report_collect() def report_collect(self, final=False): @@ -288,6 +288,10 @@ self.write_line(line) def pytest_report_header(self, config): + inifile = "" + if config.inifile: + inifile = config.rootdir.bestrelpath(config.inifile) + lines = ["rootdir: %s, inifile: %s" %(config.rootdir, inifile)] plugininfo = config.pluginmanager._plugin_distinfo if plugininfo: l = [] @@ -296,7 +300,8 @@ if name.startswith("pytest-"): name = name[7:] l.append(name) - return "plugins: %s" % ", ".join(l) + lines.append("plugins: %s" % ", ".join(l)) + return lines def pytest_collection_finish(self, session): if self.config.option.collectonly: @@ -378,19 +383,24 @@ else: excrepr.reprcrash.toterminal(self._tw) - def _locationline(self, collect_fspath, fspath, lineno, domain): + def _locationline(self, nodeid, fspath, lineno, domain): + def mkrel(nodeid): + line = self.config.cwd_relative_nodeid(nodeid) + if domain and line.endswith(domain): + line = line[:-len(domain)] + l = domain.split("[") + l[0] = l[0].replace('.', '::') # don't replace '.' in params + line += "[".join(l) + return line # collect_fspath comes from testid which has a "/"-normalized path - if fspath and fspath.replace("\\", "/") != collect_fspath: - fspath = "%s <- %s" % (collect_fspath, fspath) + if fspath: - line = str(fspath) - if domain: - split = str(domain).split('[') - split[0] = split[0].replace('.', '::') # don't replace '.' in params - line += "::" + '['.join(split) + res = mkrel(nodeid).replace("::()", "") # parens-normalization + if nodeid.split("::")[0] != fspath.replace("\\", "/"): + res += " <- " + self.startdir.bestrelpath(fspath) else: - line = "[location]" - return line + " " + res = "[location]" + return res + " " def _getfailureheadline(self, rep): if hasattr(rep, 'location'): diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 doc/en/customize.txt --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -12,37 +12,73 @@ This will display command line and configuration file settings which were registered by installed plugins. +.. _rootdir: .. _inifiles: -How test configuration is read from configuration INI-files -------------------------------------------------------------- +initialization: determining rootdir and inifile +----------------------------------------------- -``pytest`` searches for the first matching ini-style configuration file -in the directories of command line argument and the directories above. -It looks for file basenames in this order:: +.. versionadded:: 2.7 +pytest determines a "rootdir" for each test run which depends on +the command line arguments (specified test files, paths) and on +the existence of inifiles. The determined rootdir and ini-file are +printed as part of the pytest header. The rootdir is used for constructing +"nodeids" during collection and may also be used by plugins to store +project/testrun-specific information. + +Here is the algorithm which finds the rootdir from ``args``: + +- determine the common ancestor directory for the specified ``args``. + +- look for ``pytest.ini``, ``tox.ini`` and ``setup.cfg`` files in the + ancestor directory and upwards. If one is matched, it becomes the + ini-file and its directory becomes the rootdir. An existing + ``pytest.ini`` file will always be considered a match whereas + ``tox.ini`` and ``setup.cfg`` will only match if they contain + a ``[pytest]`` section. + +- if no ini-file was found, look for ``setup.py`` upwards from + the common ancestor directory to determine the ``rootdir``. + +- if no ini-file and no ``setup.py`` was found, use the already + determined common ancestor as root directory. This allows to + work with pytest in structures that are not part of a package + and don't have any particular ini-file configuration. + +Note that options from multiple ini-files candidates are never merged, +the first one wins (``pytest.ini`` always wins even if it does not +contain a ``[pytest]`` section). + +The ``config`` object will subsequently carry these attributes: + +- ``config.rootdir``: the determined root directory, guaranteed to exist. + +- ``config.inifile``: the determined ini-file, may be ``None``. + +The rootdir is used a reference directory for constructing test +addresses ("nodeids") and can be used also by plugins for storing +per-testrun information. + +Example:: + + py.test path/to/testdir path/other/ + +will determine the common ancestor as ``path`` and then +check for ini-files as follows:: + + # first look for pytest.ini files + path/pytest.ini + path/setup.cfg # must also contain [pytest] section to match + path/tox.ini # must also contain [pytest] section to match pytest.ini - tox.ini - setup.cfg + ... # all the way down to the root -Searching stops when the first ``[pytest]`` section is found in any of -these files. There is no merging of configuration values from multiple -files. Example:: + # now look for setup.py + path/setup.py + setup.py + ... # all the way down to the root - py.test path/to/testdir - -will look in the following dirs for a config file:: - - path/to/testdir/pytest.ini - path/to/testdir/tox.ini - path/to/testdir/setup.cfg - path/to/pytest.ini - path/to/tox.ini - path/to/setup.cfg - ... # up until root of filesystem - -If argument is provided to a ``pytest`` run, the current working directory -is used to start the search. .. _`how to change command line options defaults`: .. _`adding default options`: @@ -67,6 +103,8 @@ From now on, running ``pytest`` will add the specified options. + + Builtin configuration file options ---------------------------------------------- diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 testing/test_collection.py --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -343,7 +343,7 @@ ("pytest_make_collect_report", "collector.fspath == p"), ("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_collectreport", "report.nodeid.startswith(p.basename)"), - ("pytest_collectreport", "report.nodeid == '.'") + ("pytest_collectreport", "report.nodeid == ''") ]) def test_collect_protocol_method(self, testdir): @@ -478,7 +478,7 @@ config = testdir.parseconfigure(x) col = testdir.getnode(config, x) assert isinstance(col, pytest.Module) - assert col.name == 'subdir/x.py' + assert col.name == 'x.py' assert col.parent.parent is None for col in col.listchain(): assert col.config is config diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,6 +1,6 @@ import py, pytest -from _pytest.config import getcfg +from _pytest.config import getcfg, get_common_ancestor, determine_setup class TestParseIni: def test_getcfg_and_config(self, testdir, tmpdir): @@ -10,7 +10,7 @@ [pytest] name = value """)) - cfg = getcfg([sub], ["setup.cfg"]) + rootdir, inifile, cfg = getcfg([sub], ["setup.cfg"]) assert cfg['name'] == "value" config = testdir.parseconfigure(sub) assert config.inicfg['name'] == 'value' @@ -400,3 +400,55 @@ *WT1*test_warn_on_test_item*:5*hello* *1 warning* """) + +class TestRootdir: + def test_simple_noini(self, tmpdir): + assert get_common_ancestor([tmpdir]) == tmpdir + assert get_common_ancestor([tmpdir.mkdir("a"), tmpdir]) == tmpdir + assert get_common_ancestor([tmpdir, tmpdir.join("a")]) == tmpdir + with tmpdir.as_cwd(): + assert get_common_ancestor([]) == tmpdir + + @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split()) + def test_with_ini(self, tmpdir, name): + inifile = tmpdir.join(name) + inifile.write("[pytest]\n") + + a = tmpdir.mkdir("a") + b = a.mkdir("b") + for args in ([tmpdir], [a], [b]): + rootdir, inifile, inicfg = determine_setup(None, args) + assert rootdir == tmpdir + assert inifile == inifile + rootdir, inifile, inicfg = determine_setup(None, [b,a]) + assert rootdir == tmpdir + assert inifile == inifile + + @pytest.mark.parametrize("name", "setup.cfg tox.ini".split()) + def test_pytestini_overides_empty_other(self, tmpdir, name): + inifile = tmpdir.ensure("pytest.ini") + a = tmpdir.mkdir("a") + a.ensure(name) + rootdir, inifile, inicfg = determine_setup(None, [a]) + assert rootdir == tmpdir + assert inifile == inifile + + def test_setuppy_fallback(self, tmpdir): + a = tmpdir.mkdir("a") + a.ensure("setup.cfg") + tmpdir.ensure("setup.py") + rootdir, inifile, inicfg = determine_setup(None, [a]) + assert rootdir == tmpdir + assert inifile is None + assert inicfg == {} + + def test_nothing(self, tmpdir): + rootdir, inifile, inicfg = determine_setup(None, [tmpdir]) + assert rootdir == tmpdir + assert inifile is None + assert inicfg == {} + + def test_with_specific_inifile(self, tmpdir): + inifile = tmpdir.ensure("pytest.ini") + rootdir, inifile, inicfg = determine_setup(inifile, [tmpdir]) + assert rootdir == tmpdir diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 testing/test_conftest.py --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,7 +1,9 @@ +from textwrap import dedent import py, pytest from _pytest.config import Conftest + @pytest.fixture(scope="module", params=["global", "inpackage"]) def basedir(request): from _pytest.tmpdir import tmpdir @@ -255,3 +257,90 @@ result.stdout.fnmatch_lines(""" *--hello-world* """) + + +# conftest visibility, related to issue616 + +def _setup_tree(testdir): + # example mostly taken from: + # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html + runner = testdir.mkdir("empty") + package = testdir.mkdir("package") + + package.join("conftest.py").write(dedent("""\ + import pytest + @pytest.fixture + def fxtr(): + return "from-package" + """)) + package.join("test_pkgroot.py").write(dedent("""\ + def test_pkgroot(fxtr): + assert fxtr == "from-package" + """)) + + swc = package.mkdir("swc") + swc.join("__init__.py").ensure() + swc.join("conftest.py").write(dedent("""\ + import pytest + @pytest.fixture + def fxtr(): + return "from-swc" + """)) + swc.join("test_with_conftest.py").write(dedent("""\ + def test_with_conftest(fxtr): + assert fxtr == "from-swc" + + """)) + + snc = package.mkdir("snc") + snc.join("__init__.py").ensure() + snc.join("test_no_conftest.py").write(dedent("""\ + def test_no_conftest(fxtr): + assert fxtr == "from-package" # No local conftest.py, so should + # use value from parent dir's + + """)) + print ("created directory structure:") + for x in testdir.tmpdir.visit(): + print (" " + x.relto(testdir.tmpdir)) + + return { + "runner": runner, + "package": package, + "swc": swc, + "snc": snc} + +# N.B.: "swc" stands for "subdir with conftest.py" +# "snc" stands for "subdir no [i.e. without] conftest.py" + at pytest.mark.parametrize("chdir,testarg,expect_ntests_passed", [ + ("runner", "..", 3), + ("package", "..", 3), + ("swc", "../..", 3), + ("snc", "../..", 3), + + ("runner", "../package", 3), + ("package", ".", 3), + ("swc", "..", 3), + ("snc", "..", 3), + + ("runner", "../package/swc", 1), + ("package", "./swc", 1), + ("swc", ".", 1), + ("snc", "../swc", 1), + + ("runner", "../package/snc", 1), + ("package", "./snc", 1), + ("swc", "../snc", 1), + ("snc", ".", 1), +]) + at pytest.mark.issue616 +def test_parsefactories_relative_node_ids( + testdir, chdir,testarg, expect_ntests_passed): + dirs = _setup_tree(testdir) + print("pytest run in cwd: %s" %( + dirs[chdir].relto(testdir.tmpdir))) + 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) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,9 +1,6 @@ from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile import py, pytest -import pdb - - class TestDoctests: def test_collect_testtextfile(self, testdir): diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 testing/test_terminal.py --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -77,11 +77,11 @@ def test_writeline(self, testdir, linecomp): modcol = testdir.getmodulecol("def test_one(): pass") rep = TerminalReporter(modcol.config, file=linecomp.stringio) - rep.write_fspath_result(py.path.local("xy.py"), '.') + rep.write_fspath_result(modcol.nodeid, ".") rep.write_line("hello world") lines = linecomp.stringio.getvalue().split('\n') assert not lines[0] - assert lines[1].endswith("xy.py .") + assert lines[1].endswith(modcol.name + " .") assert lines[2] == "hello world" def test_show_runtest_logstart(self, testdir, linecomp): @@ -126,7 +126,7 @@ ]) result = testdir.runpytest("-v", p2) result.stdout.fnmatch_lines([ - "*test_p2.py <- *test_p1.py::TestMore::test_p1*", + "*test_p2.py::TestMore::test_p1* <- *test_p1.py*PASSED", ]) def test_itemreport_directclasses_not_shown_as_subclasses(self, testdir): Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Thu Feb 26 21:59:58 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 26 Feb 2015 20:59:58 -0000 Subject: [Pytest-commit] commit/pytest: 3 new changesets Message-ID: <20150226205958.23961.56156@app09.ash-private.bitbucket.org> 3 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/bac853daacf5/ Changeset: bac853daacf5 Branch: ignore-doctest-import-errors User: cpcloud Date: 2015-02-08 06:25:23+00:00 Summary: Add option to ignore import errors in doctests Affected #: 1 file diff -r fa62c5c63c2fb5870852676d8d8899b9656214fd -r bac853daacf5d2ba3d1ca1e5084200ecde76d88d _pytest/doctest.py --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -17,6 +17,10 @@ action="store", default="test*.txt", 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") def pytest_collect_file(path, parent): config = parent.config @@ -130,7 +134,13 @@ if self.fspath.basename == "conftest.py": module = self.config._conftest.importconftest(self.fspath) else: - module = self.fspath.pyimport() + try: + module = self.fspath.pyimport() + except ImportError: + if self.config.getvalue('doctest_ignore_import_errors'): + pytest.skip('unable to import module %r' % self.fspath) + else: + raise # satisfy `FixtureRequest` constructor... self.funcargs = {} self._fixtureinfo = FuncFixtureInfo((), [], {}) @@ -138,9 +148,9 @@ doctest_globals = dict(getfixture=fixture_request.getfuncargvalue) # uses internal doctest module parsing mechanism finder = doctest.DocTestFinder() - optionflags= get_optionflags(self) + optionflags = get_optionflags(self) runner = doctest.DebugRunner(verbose=0, optionflags=optionflags) for test in finder.find(module, module.__name__, extraglobs=doctest_globals): - if test.examples: # skip empty doctests + if test.examples: # skip empty doctests yield DoctestItem(test.name, self, runner, test) https://bitbucket.org/hpk42/pytest/commits/2b5d32cec885/ Changeset: 2b5d32cec885 Branch: ignore-doctest-import-errors User: cpcloud Date: 2015-02-26 17:39:36+00:00 Summary: Add test for command line usage Affected #: 1 file diff -r bac853daacf5d2ba3d1ca1e5084200ecde76d88d -r 2b5d32cec885a1faee1f9be15807a455d5534918 testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -349,3 +349,19 @@ """) reprec = testdir.inline_run(p, "--doctest-glob=x*.txt") reprec.assertoutcome(failed=1, passed=0) + + def test_ignore_import_errors_on_doctest(self, testdir): + p = testdir.makepyfile(""" + import asdf + + def add_one(x): + ''' + >>> add_one(1) + 2 + ''' + return x + 1 + """) + + reprec = testdir.inline_run(p, "--doctest-modules", + "--doctest-ignore-import-errors") + reprec.assertoutcome(skipped=1, failed=1, passed=0) https://bitbucket.org/hpk42/pytest/commits/eeaef9601d3f/ Changeset: eeaef9601d3f User: hpk42 Date: 2015-02-26 20:59:54+00:00 Summary: Merged in cpcloud/pytest/ignore-doctest-import-errors (pull request #243) Add option to ignore import errors in doctests Affected #: 2 files diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r eeaef9601d3f2996c3bbbc4c0301a859d8bc35b5 _pytest/doctest.py --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -17,6 +17,10 @@ action="store", default="test*.txt", 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") def pytest_collect_file(path, parent): config = parent.config @@ -130,7 +134,13 @@ if self.fspath.basename == "conftest.py": module = self.config._conftest.importconftest(self.fspath) else: - module = self.fspath.pyimport() + try: + module = self.fspath.pyimport() + except ImportError: + if self.config.getvalue('doctest_ignore_import_errors'): + pytest.skip('unable to import module %r' % self.fspath) + else: + raise # satisfy `FixtureRequest` constructor... self.funcargs = {} self._fixtureinfo = FuncFixtureInfo((), [], {}) @@ -138,9 +148,9 @@ doctest_globals = dict(getfixture=fixture_request.getfuncargvalue) # uses internal doctest module parsing mechanism finder = doctest.DocTestFinder() - optionflags= get_optionflags(self) + optionflags = get_optionflags(self) runner = doctest.DebugRunner(verbose=0, optionflags=optionflags) for test in finder.find(module, module.__name__, extraglobs=doctest_globals): - if test.examples: # skip empty doctests + if test.examples: # skip empty doctests yield DoctestItem(test.name, self, runner, test) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r eeaef9601d3f2996c3bbbc4c0301a859d8bc35b5 testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -341,3 +341,19 @@ """) reprec = testdir.inline_run(p, "--doctest-glob=x*.txt") reprec.assertoutcome(failed=1, passed=0) + + def test_ignore_import_errors_on_doctest(self, testdir): + p = testdir.makepyfile(""" + import asdf + + def add_one(x): + ''' + >>> add_one(1) + 2 + ''' + return x + 1 + """) + + reprec = testdir.inline_run(p, "--doctest-modules", + "--doctest-ignore-import-errors") + reprec.assertoutcome(skipped=1, failed=1, passed=0) Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Thu Feb 26 21:59:59 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Thu, 26 Feb 2015 20:59:59 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: Merged in cpcloud/pytest/ignore-doctest-import-errors (pull request #243) Message-ID: <20150226205959.29100.79220@app10.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/eeaef9601d3f/ Changeset: eeaef9601d3f User: hpk42 Date: 2015-02-26 20:59:54+00:00 Summary: Merged in cpcloud/pytest/ignore-doctest-import-errors (pull request #243) Add option to ignore import errors in doctests Affected #: 2 files diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r eeaef9601d3f2996c3bbbc4c0301a859d8bc35b5 _pytest/doctest.py --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -17,6 +17,10 @@ action="store", default="test*.txt", 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") def pytest_collect_file(path, parent): config = parent.config @@ -130,7 +134,13 @@ if self.fspath.basename == "conftest.py": module = self.config._conftest.importconftest(self.fspath) else: - module = self.fspath.pyimport() + try: + module = self.fspath.pyimport() + except ImportError: + if self.config.getvalue('doctest_ignore_import_errors'): + pytest.skip('unable to import module %r' % self.fspath) + else: + raise # satisfy `FixtureRequest` constructor... self.funcargs = {} self._fixtureinfo = FuncFixtureInfo((), [], {}) @@ -138,9 +148,9 @@ doctest_globals = dict(getfixture=fixture_request.getfuncargvalue) # uses internal doctest module parsing mechanism finder = doctest.DocTestFinder() - optionflags= get_optionflags(self) + optionflags = get_optionflags(self) runner = doctest.DebugRunner(verbose=0, optionflags=optionflags) for test in finder.find(module, module.__name__, extraglobs=doctest_globals): - if test.examples: # skip empty doctests + if test.examples: # skip empty doctests yield DoctestItem(test.name, self, runner, test) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r eeaef9601d3f2996c3bbbc4c0301a859d8bc35b5 testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -341,3 +341,19 @@ """) reprec = testdir.inline_run(p, "--doctest-glob=x*.txt") reprec.assertoutcome(failed=1, passed=0) + + def test_ignore_import_errors_on_doctest(self, testdir): + p = testdir.makepyfile(""" + import asdf + + def add_one(x): + ''' + >>> add_one(1) + 2 + ''' + return x + 1 + """) + + reprec = testdir.inline_run(p, "--doctest-modules", + "--doctest-ignore-import-errors") + reprec.assertoutcome(skipped=1, failed=1, passed=0) Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Thu Feb 26 22:05:19 2015 From: builds at drone.io (Drone.io Build) Date: Thu, 26 Feb 2015 21:05:19 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 387 Message-ID: <20150226210506.77528.20752@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/387 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3866:327ead9d7e9b Author : holger krekel Branch : issue616 Message: fix issue616 - conftest visibility fixes. This is achieved by -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 07:18:28 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 06:18:28 -0000 Subject: [Pytest-commit] commit/pytest: 4 new changesets Message-ID: <20150227061828.20004.51884@app06.ash-private.bitbucket.org> 4 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/ef582d901aeb/ Changeset: ef582d901aeb Branch: merge-cache User: RonnyPfannschmidt Date: 2015-02-27 05:26:57+00:00 Summary: simply copy the files, fails all tests Affected #: 8 files diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e _pytest/cache.py --- /dev/null +++ b/_pytest/cache.py @@ -0,0 +1,201 @@ +import py +import pytest +import json + + +class Cache: + def __init__(self, config): + self.config = config + self._cachedir = getrootdir(config, ".cache") + self.trace = config.trace.root.get("cache") + if config.getvalue("clearcache"): + self.trace("clearing cachedir") + if self._cachedir.check(): + self._cachedir.remove() + self._cachedir.mkdir() + + def makedir(self, name): + """ return a directory path object with the given name. If the + directory does not yet exist, it will be created. You can use it + to manage files likes e. g. store/retrieve database + dumps across test sessions. + + :param name: must be a string not containing a ``/`` separator. + Make sure the name contains your plugin or application + identifiers to prevent clashes with other cache users. + """ + if name.count("/") != 0: + raise ValueError("name is not allowed to contain '/'") + p = self._cachedir.join("d/" + name) + p.ensure(dir=1) + return p + + def _getpath(self, key): + if not key.count("/") > 1: + raise KeyError("Key must be of format 'dir/.../subname") + return self._cachedir.join(key) + + def _getvaluepath(self, key): + p = self._getpath("v/" + key) + p.dirpath().ensure(dir=1) + return p + + def get(self, key, default): + """ return cached value for the given key. If no value + was yet cached or the value cannot be read, the specified + default is returned. + + :param key: must be a ``/`` separated value. Usually the first + name is the name of your plugin or your application. + :param default: must be provided in case of a cache-miss or + invalid cache values. + + """ + path = self._getvaluepath(key) + if path.check(): + try: + with path.open("r") as f: + return json.load(f) + except ValueError: + self.trace("cache-invalid at %s" % (path,)) + return default + + def set(self, key, value): + """ save value for the given key. + + :param key: must be a ``/`` separated value. Usually the first + name is the name of your plugin or your application. + :param value: must be of any combination of basic + python types, including nested types + like e. g. lists of dictionaries. + """ + path = self._getvaluepath(key) + with path.open("w") as f: + self.trace("cache-write %s: %r" % (key, value,)) + json.dump(value, f, indent=2, sort_keys=True) + + +### XXX consider shifting part of the below to pytest config object + +def getrootdir(config, name): + """ return a best-effort root subdir for this test run. + + Starting from files specified at the command line (or cwd) + search starts upward for the first "tox.ini", "pytest.ini", + "setup.cfg" or "setup.py" file. The first directory containing + such a file will be used to return a named subdirectory + (py.path.local object). + + """ + if config.inicfg: + p = py.path.local(config.inicfg.config.path).dirpath() + else: + inibasenames = ["setup.py", "setup.cfg", "tox.ini", "pytest.ini"] + for x in getroot(config.args, inibasenames): + p = x.dirpath() + break + else: + p = py.path.local() + config.trace.get("warn")("no rootdir found, using %s" % p) + subdir = p.join(name) + config.trace("root %s: %s" % (name, subdir)) + return subdir + +def getroot(args, inibasenames): + args = [x for x in args if not str(x).startswith("-")] + if not args: + args = [py.path.local()] + for arg in args: + arg = py.path.local(arg) + for base in arg.parts(reverse=True): + for inibasename in inibasenames: + p = base.join(inibasename) + if p.check(): + yield p + + +import py +import pytest + + +def pytest_addoption(parser): + group = parser.getgroup("general") + group.addoption( + '--lf', action='store_true', dest="lf", + help="rerun only the tests that failed at the last run (or all if none failed)") + group.addoption( + '--ff', action='store_true', dest="failedfirst", + help="run all tests but run the last failures first. This may re-order " + "tests and thus lead to repeated fixture setup/teardown") + group.addoption( + '--cache', action='store_true', dest="showcache", + help="show cache contents, don't perform collection or tests") + group.addoption( + '--clearcache', action='store_true', dest="clearcache", + help="remove all cache contents at start of test run.") + group.addoption( + '--looponchange', action='store_true', dest='looponchange', + help='rerun every time the workdir changes') + group.addoption( + '--looponfail', action='store_true', dest='looponfail', + help='rerun every time the workdir changes') + parser.addini( + "looponchangeroots", type="pathlist", + help="directories to check for changes", default=[py.path.local()]) + + +def pytest_cmdline_main(config): + if config.option.showcache: + from _pytest.main import wrap_session + return wrap_session(config, showcache) + if config.option.looponchange or config.option.looponfail: + from .onchange import looponchange + return looponchange(config) + + + at pytest.mark.tryfirst +def pytest_configure(config): + from .cache import Cache + from .lastfail import LFPlugin + config.cache = cache = Cache(config) + config.pluginmanager.register(LFPlugin(config), "lfplugin") + +def pytest_report_header(config): + if config.option.verbose: + relpath = py.path.local().bestrelpath(config.cache._cachedir) + return "cachedir: %s" % config.cache._cachedir + +def showcache(config, session): + from pprint import pprint + tw = py.io.TerminalWriter() + tw.line("cachedir: " + str(config.cache._cachedir)) + if not config.cache._cachedir.check(): + tw.line("cache is empty") + return 0 + dummy = object() + basedir = config.cache._cachedir + vdir = basedir.join("v") + tw.sep("-", "cache values") + for valpath in vdir.visit(lambda x: x.check(file=1)): + key = valpath.relto(vdir).replace(valpath.sep, "/") + val = config.cache.get(key, dummy) + if val is dummy: + tw.line("%s contains unreadable content, " + "will be ignored" % key) + else: + tw.line("%s contains:" % key) + stream = py.io.TextIO() + pprint(val, stream=stream) + for line in stream.getvalue().splitlines(): + tw.line(" " + line) + + ddir = basedir.join("d") + if ddir.check(dir=1) and ddir.listdir(): + tw.sep("-", "cache directories") + for p in basedir.join("d").visit(): + #if p.check(dir=1): + # print("%s/" % p.relto(basedir)) + if p.check(file=1): + key = p.relto(basedir) + tw.line("%s is a file of length %d" % ( + key, p.size())) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e _pytest/lastfail.py --- /dev/null +++ b/_pytest/lastfail.py @@ -0,0 +1,65 @@ + + +class LFPlugin: + """ Plugin which implements the --lf (run last-failing) option """ + def __init__(self, config): + self.config = config + active_keys = 'lf', 'failedfirst', 'looponfail' + self.active = any(config.getvalue(key) for key in active_keys) + if self.active: + self.lastfailed = config.cache.get("cache/lastfailed", {}) + else: + self.lastfailed = {} + + def pytest_report_header(self): + if self.active: + if not self.lastfailed: + mode = "run all (no recorded failures)" + else: + mode = "rerun last %d failures%s" % ( + len(self.lastfailed), + " first" if self.config.getvalue("failedfirst") else "") + return "run-last-failure: %s" % mode + + def pytest_runtest_logreport(self, report): + if report.failed and "xfail" not in report.keywords: + self.lastfailed[report.nodeid] = True + elif not report.failed: + if report.when == "call": + self.lastfailed.pop(report.nodeid, None) + + def pytest_collectreport(self, report): + passed = report.outcome in ('passed', 'skipped') + if passed: + if report.nodeid in self.lastfailed: + self.lastfailed.pop(report.nodeid) + self.lastfailed.update( + (item.nodeid, True) + for item in report.result) + else: + self.lastfailed[report.nodeid] = True + + def pytest_collection_modifyitems(self, session, config, items): + if self.active and self.lastfailed: + previously_failed = [] + previously_passed = [] + for item in items: + if item.nodeid in self.lastfailed: + previously_failed.append(item) + else: + previously_passed.append(item) + if not previously_failed and previously_passed: + # running a subset of all tests with recorded failures outside + # of the set of tests currently executing + pass + elif self.config.getvalue("failedfirst"): + items[:] = previously_failed + previously_passed + else: + items[:] = previously_failed + config.hook.pytest_deselected(items=previously_passed) + + def pytest_sessionfinish(self, session): + config = self.config + if config.getvalue("showcache") or hasattr(config, "slaveinput"): + return + config.cache.set("cache/lastfailed", self.lastfailed) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e _pytest/onchange.py --- /dev/null +++ b/_pytest/onchange.py @@ -0,0 +1,75 @@ +import py + + +SCRIPT = """ +import pytest +pytest.main(%r) +""" + + +def looponchange(config): + newargs = config._origargs[:] + newargs.remove('--looponchange') + stats = StatRecorder(config.getini('looponchangeroots')) + command = py.std.functools.partial( + py.std.subprocess.call, [ + py.std.sys.executable, + '-c', SCRIPT % newargs]) + loop_forever(stats, command) + return 2 + + +def loop_forever(stats, command): + while True: + stats.waitonchange() + command() + + +class StatRecorder(object): + def __init__(self, rootdirlist): + self.rootdirlist = rootdirlist + self.statcache = {} + self.check() # snapshot state + + def fil(self, p): + return p.check(file=1, dotfile=0) and p.ext != ".pyc" + def rec(self, p): + return p.check(dotfile=0) + + def waitonchange(self, checkinterval=1.0): + while 1: + changed = self.check() + if changed: + return + py.std.time.sleep(checkinterval) + + def check(self, removepycfiles=True): + changed = False + statcache = self.statcache + newstat = {} + for rootdir in self.rootdirlist: + for path in rootdir.visit(self.fil, self.rec): + oldstat = statcache.pop(path, None) + try: + newstat[path] = curstat = path.stat() + except py.error.ENOENT: + if oldstat: + changed = True + else: + if oldstat: + if oldstat.mtime != curstat.mtime or \ + oldstat.size != curstat.size: + changed = True + py.builtin.print_("# MODIFIED", path) + if removepycfiles and path.ext == ".py": + pycfile = path + "c" + if pycfile.check(): + pycfile.remove() + + else: + changed = True + if statcache: + changed = True + self.statcache = newstat + return changed + diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e _pytest/plugin.py --- /dev/null +++ b/_pytest/plugin.py @@ -0,0 +1,85 @@ +import py +import pytest + + +def pytest_addoption(parser): + group = parser.getgroup("general") + group.addoption( + '--lf', action='store_true', dest="lf", + help="rerun only the tests that failed at the last run (or all if none failed)") + group.addoption( + '--ff', action='store_true', dest="failedfirst", + help="run all tests but run the last failures first. This may re-order " + "tests and thus lead to repeated fixture setup/teardown") + group.addoption( + '--cache', action='store_true', dest="showcache", + help="show cache contents, don't perform collection or tests") + group.addoption( + '--clearcache', action='store_true', dest="clearcache", + help="remove all cache contents at start of test run.") + group.addoption( + '--looponchange', action='store_true', dest='looponchange', + help='rerun every time the workdir changes') + group.addoption( + '--looponfail', action='store_true', dest='looponfail', + help='rerun every time the workdir changes') + parser.addini( + "looponchangeroots", type="pathlist", + help="directories to check for changes", default=[py.path.local()]) + + +def pytest_cmdline_main(config): + if config.option.showcache: + from _pytest.main import wrap_session + return wrap_session(config, showcache) + if config.option.looponchange or config.option.looponfail: + from .onchange import looponchange + return looponchange(config) + + + at pytest.mark.tryfirst +def pytest_configure(config): + from .cache import Cache + from .lastfail import LFPlugin + config.cache = cache = Cache(config) + config.pluginmanager.register(LFPlugin(config), "lfplugin") + +def pytest_report_header(config): + if config.option.verbose: + relpath = py.path.local().bestrelpath(config.cache._cachedir) + return "cachedir: %s" % config.cache._cachedir + +def showcache(config, session): + from pprint import pprint + tw = py.io.TerminalWriter() + tw.line("cachedir: " + str(config.cache._cachedir)) + if not config.cache._cachedir.check(): + tw.line("cache is empty") + return 0 + dummy = object() + basedir = config.cache._cachedir + vdir = basedir.join("v") + tw.sep("-", "cache values") + for valpath in vdir.visit(lambda x: x.check(file=1)): + key = valpath.relto(vdir).replace(valpath.sep, "/") + val = config.cache.get(key, dummy) + if val is dummy: + tw.line("%s contains unreadable content, " + "will be ignored" % key) + else: + tw.line("%s contains:" % key) + stream = py.io.TextIO() + pprint(val, stream=stream) + for line in stream.getvalue().splitlines(): + tw.line(" " + line) + + ddir = basedir.join("d") + if ddir.check(dir=1) and ddir.listdir(): + tw.sep("-", "cache directories") + for p in basedir.join("d").visit(): + #if p.check(dir=1): + # print("%s/" % p.relto(basedir)) + if p.check(file=1): + key = p.relto(basedir) + tw.line("%s is a file of length %d" % ( + key, p.size())) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e testing/test_cache.py --- /dev/null +++ b/testing/test_cache.py @@ -0,0 +1,54 @@ +import os +import pytest +import shutil +import py + +pytest_plugins = "pytester", + +class TestNewAPI: + def test_config_cache_makedir(self, testdir): + testdir.makeini("[pytest]") + config = testdir.parseconfigure() + pytest.raises(ValueError, lambda: + config.cache.makedir("key/name")) + p = config.cache.makedir("name") + assert p.check() + + def test_config_cache_dataerror(self, testdir): + testdir.makeini("[pytest]") + config = testdir.parseconfigure() + cache = config.cache + pytest.raises(TypeError, lambda: cache.set("key/name", cache)) + config.cache.set("key/name", 0) + config.cache._getvaluepath("key/name").write("123invalid") + val = config.cache.get("key/name", -2) + assert val == -2 + + def test_config_cache(self, testdir): + testdir.makeconftest(""" + def pytest_configure(config): + # see that we get cache information early on + assert hasattr(config, "cache") + """) + testdir.makepyfile(""" + def test_session(pytestconfig): + assert hasattr(pytestconfig, "cache") + """) + result = testdir.runpytest() + assert result.ret == 0 + result.stdout.fnmatch_lines(["*1 passed*"]) + + def XXX_test_cachefuncarg(self, testdir): + testdir.makepyfile(""" + import pytest + def test_cachefuncarg(cache): + val = cache.get("some/thing", None) + assert val is None + cache.set("some/thing", [1]) + pytest.raises(TypeError, lambda: cache.get("some/thing")) + val = cache.get("some/thing", []) + assert val == [1] + """) + result = testdir.runpytest() + assert result.ret == 0 + result.stdout.fnmatch_lines(["*1 passed*"]) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e testing/test_lastfailed.py --- /dev/null +++ b/testing/test_lastfailed.py @@ -0,0 +1,235 @@ +import os +import pytest +import shutil +import py + +pytest_plugins = "pytester", + + +class TestLastFailed: + @pytest.mark.skipif("sys.version_info < (2,6)") + def test_lastfailed_usecase(self, testdir, monkeypatch): + monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) + p = testdir.makepyfile(""" + def test_1(): + assert 0 + def test_2(): + assert 0 + def test_3(): + assert 1 + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + p.write(py.code.Source(""" + def test_1(): + assert 1 + + def test_2(): + assert 1 + + def test_3(): + assert 0 + """)) + result = testdir.runpytest("--lf") + result.stdout.fnmatch_lines([ + "*2 passed*1 desel*", + ]) + result = testdir.runpytest("--lf") + result.stdout.fnmatch_lines([ + "*1 failed*2 passed*", + ]) + result = testdir.runpytest("--lf", "--clearcache") + result.stdout.fnmatch_lines([ + "*1 failed*2 passed*", + ]) + + # Run this again to make sure clearcache is robust + if os.path.isdir('.cache'): + shutil.rmtree('.cache') + result = testdir.runpytest("--lf", "--clearcache") + result.stdout.fnmatch_lines([ + "*1 failed*2 passed*", + ]) + + def test_failedfirst_order(self, testdir): + always_pass = testdir.tmpdir.join('test_a.py').write(py.code.Source(""" + def test_always_passes(): + assert 1 + """)) + always_fail = testdir.tmpdir.join('test_b.py').write(py.code.Source(""" + def test_always_fails(): + assert 0 + """)) + result = testdir.runpytest() + # Test order will be collection order; alphabetical + result.stdout.fnmatch_lines([ + "test_a.py*", + "test_b.py*", + ]) + result = testdir.runpytest("--lf", "--ff") + # Test order will be failing tests firs + result.stdout.fnmatch_lines([ + "test_b.py*", + "test_a.py*", + ]) + + @pytest.mark.skipif("sys.version_info < (2,6)") + def test_lastfailed_difference_invocations(self, testdir, monkeypatch): + monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) + testdir.makepyfile(test_a=""" + def test_a1(): + assert 0 + def test_a2(): + assert 1 + """, test_b=""" + def test_b1(): + assert 0 + """) + p = testdir.tmpdir.join("test_a.py") + p2 = testdir.tmpdir.join("test_b.py") + + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + result = testdir.runpytest("--lf", p2) + result.stdout.fnmatch_lines([ + "*1 failed*", + ]) + p2.write(py.code.Source(""" + def test_b1(): + assert 1 + """)) + result = testdir.runpytest("--lf", p2) + result.stdout.fnmatch_lines([ + "*1 passed*", + ]) + result = testdir.runpytest("--lf", p) + result.stdout.fnmatch_lines([ + "*1 failed*1 desel*", + ]) + + @pytest.mark.skipif("sys.version_info < (2,6)") + def test_lastfailed_usecase_splice(self, testdir, monkeypatch): + monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) + p1 = testdir.makepyfile(""" + def test_1(): + assert 0 + """) + p2 = testdir.tmpdir.join("test_something.py") + p2.write(py.code.Source(""" + def test_2(): + assert 0 + """)) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + result = testdir.runpytest("--lf", p2) + result.stdout.fnmatch_lines([ + "*1 failed*", + ]) + result = testdir.runpytest("--lf") + result.stdout.fnmatch_lines([ + "*2 failed*", + ]) + + def test_lastfailed_xpass(self, testdir): + rep = testdir.inline_runsource1(""" + import pytest + @pytest.mark.xfail + def test_hello(): + assert 1 + """) + config = testdir.parseconfigure() + lastfailed = config.cache.get("cache/lastfailed", -1) + assert not lastfailed + + def test_lastfailed_collectfailure(self, testdir, monkeypatch): + + testdir.makepyfile(test_maybe=""" + import py + env = py.std.os.environ + if '1' == env['FAILIMPORT']: + raise ImportError('fail') + def test_hello(): + assert '0' == env['FAILTEST'] + """) + + def rlf(fail_import, fail_run): + monkeypatch.setenv('FAILIMPORT', fail_import) + monkeypatch.setenv('FAILTEST', fail_run) + + testdir.runpytest('-q') + config = testdir.parseconfigure() + lastfailed = config.cache.get("cache/lastfailed", -1) + return lastfailed + + lastfailed = rlf(fail_import=0, fail_run=0) + assert not lastfailed + + lastfailed = rlf(fail_import=1, fail_run=0) + assert list(lastfailed) == ['test_maybe.py'] + + 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=""" + import py + env = py.std.os.environ + if '1' == env['FAILIMPORT']: + raise ImportError('fail') + def test_hello(): + assert '0' == env['FAILTEST'] + """) + + testdir.makepyfile(test_maybe2=""" + import py + env = py.std.os.environ + if '1' == env['FAILIMPORT']: + raise ImportError('fail') + def test_hello(): + assert '0' == env['FAILTEST'] + + def test_pass(): + pass + """) + + def rlf(fail_import, fail_run, args=()): + monkeypatch.setenv('FAILIMPORT', fail_import) + monkeypatch.setenv('FAILTEST', fail_run) + + result = testdir.runpytest('-q', '--lf', *args) + config = testdir.parseconfigure() + lastfailed = config.cache.get("cache/lastfailed", -1) + return result, lastfailed + + result, lastfailed = rlf(fail_import=0, fail_run=0) + assert not lastfailed + result.stdout.fnmatch_lines([ + '*3 passed*', + ]) + + 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 + result, lastfailed = rlf(fail_import=0, fail_run=0, + args=('test_maybe2.py',)) + assert list(lastfailed) == ['test_maybe.py'] + result.stdout.fnmatch_lines([ + '*2 passed*', + ]) diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e testing/test_onchange.py --- /dev/null +++ b/testing/test_onchange.py @@ -0,0 +1,88 @@ +from pytest_cache.onchange import StatRecorder + +class TestStatRecorder: + def test_filechange(self, tmpdir): + tmp = tmpdir + hello = tmp.ensure("hello.py") + sd = StatRecorder([tmp]) + changed = sd.check() + assert not changed + + hello.write("world") + changed = sd.check() + assert changed + + (hello + "c").write("hello") + changed = sd.check() + assert not changed + + p = tmp.ensure("new.py") + changed = sd.check() + assert changed + + p.remove() + changed = sd.check() + assert changed + + tmp.join("a", "b", "c.py").ensure() + changed = sd.check() + assert changed + + tmp.join("a", "c.txt").ensure() + changed = sd.check() + assert changed + changed = sd.check() + assert not changed + + tmp.join("a").remove() + changed = sd.check() + assert changed + + def test_dirchange(self, tmpdir): + tmp = tmpdir + hello = tmp.ensure("dir", "hello.py") + sd = StatRecorder([tmp]) + assert not sd.fil(tmp.join("dir")) + + def test_filechange_deletion_race(self, tmpdir, monkeypatch): + tmp = tmpdir + sd = StatRecorder([tmp]) + changed = sd.check() + assert not changed + + p = tmp.ensure("new.py") + changed = sd.check() + assert changed + + p.remove() + # make check()'s visit() call return our just removed + # path as if we were in a race condition + monkeypatch.setattr(tmp, 'visit', lambda *args: [p]) + + changed = sd.check() + assert changed + + def test_pycremoval(self, tmpdir): + tmp = tmpdir + hello = tmp.ensure("hello.py") + sd = StatRecorder([tmp]) + changed = sd.check() + assert not changed + + pycfile = hello + "c" + pycfile.ensure() + hello.write("world") + changed = sd.check() + assert changed + assert not pycfile.check() + + def test_waitonchange(self, tmpdir, monkeypatch): + tmp = tmpdir + sd = StatRecorder([tmp]) + + l = [True, False] + monkeypatch.setattr(StatRecorder, 'check', lambda self: l.pop()) + sd.waitonchange(checkinterval=0.2) + assert not l + + diff -r 6104c7ea0dccd13b892fa021a2fc989f60a8ff59 -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e testing/test_plugin.py --- /dev/null +++ b/testing/test_plugin.py @@ -0,0 +1,50 @@ +import os +import pytest +import shutil +import py + +pytest_plugins = "pytester", + +def test_version(): + import pytest_cache + assert pytest_cache.__version__ + +def test_cache_reportheader(testdir): + p = testdir.makepyfile(""" + def test_hello(): + pass + """) + cachedir = p.dirpath(".cache") + result = testdir.runpytest("-v") + result.stdout.fnmatch_lines([ + "cachedir: %s" % cachedir, + ]) + +def test_cache_show(testdir): + result = testdir.runpytest("--cache") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + "*cache is empty*" + ]) + p = testdir.makeconftest(""" + def pytest_configure(config): + config.cache.set("my/name", [1,2,3]) + config.cache.set("other/some", {1:2}) + dp = config.cache.makedir("mydb") + dp.ensure("hello") + dp.ensure("world") + """) + result = testdir.runpytest() + assert result.ret == 0 + result = testdir.runpytest("--cache") + result.stdout.fnmatch_lines_random([ + "*cachedir:*", + "-*cache values*-", + "*my/name contains:", + " [1, 2, 3]", + "*other/some contains*", + " {*1*: 2}", + "-*cache directories*-", + "*mydb/hello*length 0*", + "*mydb/world*length 0*", + ]) https://bitbucket.org/hpk42/pytest/commits/92cace41d1b6/ Changeset: 92cace41d1b6 Branch: merge-cache User: RonnyPfannschmidt Date: 2015-02-26 18:24:35+00:00 Summary: make the tests pass, this is the baselevel for creating backward compat Affected #: 8 files diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -51,7 +51,7 @@ default_plugins = ( "mark main terminal runner python pdb unittest capture skipping " "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript " - "junitxml resultlog doctest").split() + "junitxml resultlog doctest cache").split() def _preloadplugins(): assert not _preinit diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 _pytest/core.py --- a/_pytest/core.py +++ b/_pytest/core.py @@ -10,7 +10,11 @@ assert py.__version__.split(".")[:2] >= ['1', '4'], ("installation problem: " "%s is too old, remove or upgrade 'py'" % (py.__version__)) -py3 = sys.version_info > (3,0) +py3 = sys.version_info > (3, 0) + +# +_ALREADY_INCLUDED_PLUGINS = 'pytest-cache', + class TagTracer: def __init__(self): @@ -269,6 +273,11 @@ except ImportError: return # XXX issue a warning for ep in iter_entry_points('pytest11'): + project_name = getattr(ep.dist, 'project_name', None) + if project_name in _ALREADY_INCLUDED_PLUGINS: + self._warnings.append( + 'ignoring now included plugin ' + project_name) + continue name = ep.name if name.startswith("pytest_"): name = name[7:] diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 _pytest/plugin.py --- a/_pytest/plugin.py +++ /dev/null @@ -1,85 +0,0 @@ -import py -import pytest - - -def pytest_addoption(parser): - group = parser.getgroup("general") - group.addoption( - '--lf', action='store_true', dest="lf", - help="rerun only the tests that failed at the last run (or all if none failed)") - group.addoption( - '--ff', action='store_true', dest="failedfirst", - help="run all tests but run the last failures first. This may re-order " - "tests and thus lead to repeated fixture setup/teardown") - group.addoption( - '--cache', action='store_true', dest="showcache", - help="show cache contents, don't perform collection or tests") - group.addoption( - '--clearcache', action='store_true', dest="clearcache", - help="remove all cache contents at start of test run.") - group.addoption( - '--looponchange', action='store_true', dest='looponchange', - help='rerun every time the workdir changes') - group.addoption( - '--looponfail', action='store_true', dest='looponfail', - help='rerun every time the workdir changes') - parser.addini( - "looponchangeroots", type="pathlist", - help="directories to check for changes", default=[py.path.local()]) - - -def pytest_cmdline_main(config): - if config.option.showcache: - from _pytest.main import wrap_session - return wrap_session(config, showcache) - if config.option.looponchange or config.option.looponfail: - from .onchange import looponchange - return looponchange(config) - - - at pytest.mark.tryfirst -def pytest_configure(config): - from .cache import Cache - from .lastfail import LFPlugin - config.cache = cache = Cache(config) - config.pluginmanager.register(LFPlugin(config), "lfplugin") - -def pytest_report_header(config): - if config.option.verbose: - relpath = py.path.local().bestrelpath(config.cache._cachedir) - return "cachedir: %s" % config.cache._cachedir - -def showcache(config, session): - from pprint import pprint - tw = py.io.TerminalWriter() - tw.line("cachedir: " + str(config.cache._cachedir)) - if not config.cache._cachedir.check(): - tw.line("cache is empty") - return 0 - dummy = object() - basedir = config.cache._cachedir - vdir = basedir.join("v") - tw.sep("-", "cache values") - for valpath in vdir.visit(lambda x: x.check(file=1)): - key = valpath.relto(vdir).replace(valpath.sep, "/") - val = config.cache.get(key, dummy) - if val is dummy: - tw.line("%s contains unreadable content, " - "will be ignored" % key) - else: - tw.line("%s contains:" % key) - stream = py.io.TextIO() - pprint(val, stream=stream) - for line in stream.getvalue().splitlines(): - tw.line(" " + line) - - ddir = basedir.join("d") - if ddir.check(dir=1) and ddir.listdir(): - tw.sep("-", "cache directories") - for p in basedir.join("d").visit(): - #if p.check(dir=1): - # print("%s/" % p.relto(basedir)) - if p.check(file=1): - key = p.relto(basedir) - tw.line("%s is a file of length %d" % ( - key, p.size())) diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -307,6 +307,7 @@ assert name == "pytest11" class EntryPoint: name = "mytestplugin" + dist = None def load(self): assert 0, "should not arrive here" return iter([EntryPoint()]) diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 testing/test_core.py --- a/testing/test_core.py +++ b/testing/test_core.py @@ -70,12 +70,13 @@ assert name == "pytest11" class EntryPoint: name = "pytest_mytestplugin" - dist = None + class dist: + name = None def load(self): class PseudoPlugin: x = 42 return PseudoPlugin() - return iter([EntryPoint()]) + yield EntryPoint() monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) pluginmanager = PluginManager() @@ -83,6 +84,28 @@ plugin = pluginmanager.getplugin("mytestplugin") assert plugin.x == 42 + @pytest.mark.parametrize('distname', ['pytest-cache']) + def test_dont_consider_setuptools_included(self, distname, monkeypatch): + pkg_resources = pytest.importorskip("pkg_resources") + def my_iter(name): + assert name == "pytest11" + class EntryPoint: + name = "pytest_mytestplugin" + class dist: + project_name = distname + def load(self): + class PseudoPlugin: + x = 42 + return PseudoPlugin() + yield EntryPoint() + + monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) + pluginmanager = PluginManager() + pluginmanager.consider_setuptools_entrypoints() + plugin = pluginmanager.getplugin("mytestplugin") + assert plugin is None + + def test_consider_setuptools_not_installed(self, monkeypatch): monkeypatch.setitem(py.std.sys.modules, 'pkg_resources', py.std.types.ModuleType("pkg_resources")) diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 testing/test_onchange.py --- a/testing/test_onchange.py +++ b/testing/test_onchange.py @@ -1,4 +1,4 @@ -from pytest_cache.onchange import StatRecorder +from _pytest.onchange import StatRecorder class TestStatRecorder: def test_filechange(self, tmpdir): diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 testing/test_plugin.py --- a/testing/test_plugin.py +++ b/testing/test_plugin.py @@ -5,9 +5,6 @@ pytest_plugins = "pytester", -def test_version(): - import pytest_cache - assert pytest_cache.__version__ def test_cache_reportheader(testdir): p = testdir.makepyfile(""" diff -r ef582d901aeb52d7bf62acfdb2358ab184b0d37e -r 92cace41d1b64f910484cd45e54954c65f6de447 tox.ini --- a/tox.ini +++ b/tox.ini @@ -15,8 +15,9 @@ [testenv:flakes] changedir= -deps = pytest-flakes>=0.2 -commands = py.test --flakes -m flakes _pytest testing +deps = flake8 + mccabe +commands = pytest.py _pytest testing [testenv:py27-xdist] changedir=. @@ -141,5 +142,8 @@ python_files=test_*.py *_test.py testing/*/*.py python_classes=Test Acceptance python_functions=test -pep8ignore = E401 E225 E261 E128 E124 E302 norecursedirs = .tox ja .hg + + +[flake8] +ignore = E401 E225 E261 E128 E124 E302 https://bitbucket.org/hpk42/pytest/commits/e6a40d65fe50/ Changeset: e6a40d65fe50 Branch: merge-cache User: RonnyPfannschmidt Date: 2015-02-26 18:24:39+00:00 Summary: finish backward compat for looponfail Affected #: 2 files diff -r 92cace41d1b64f910484cd45e54954c65f6de447 -r e6a40d65fe5071539fa1ecd07af7f5831504a436 _pytest/cache.py --- a/_pytest/cache.py +++ b/_pytest/cache.py @@ -1,7 +1,8 @@ import py import pytest import json - +import sys +import pkg_resources class Cache: def __init__(self, config): @@ -114,11 +115,15 @@ yield p -import py -import pytest - def pytest_addoption(parser): + try: + ls = pkg_resources.resource_listdir('xdist', '.') + except: + outside_looponfail = False + else: + outside_looponfail = 'looponfail.py' in ls + group = parser.getgroup("general") group.addoption( '--lf', action='store_true', dest="lf", @@ -136,9 +141,10 @@ group.addoption( '--looponchange', action='store_true', dest='looponchange', help='rerun every time the workdir changes') - group.addoption( - '--looponfail', action='store_true', dest='looponfail', - help='rerun every time the workdir changes') + if not outside_looponfail: + group._addoption( + '-f', '--looponfail', action='store_true', dest='looponfail', + help='rerun every time the workdir changes') parser.addini( "looponchangeroots", type="pathlist", help="directories to check for changes", default=[py.path.local()]) diff -r 92cace41d1b64f910484cd45e54954c65f6de447 -r e6a40d65fe5071539fa1ecd07af7f5831504a436 _pytest/onchange.py --- a/_pytest/onchange.py +++ b/_pytest/onchange.py @@ -1,5 +1,5 @@ import py - +import subprocess SCRIPT = """ import pytest @@ -7,14 +7,24 @@ """ +def run_once(args, tw=None): + tw = py.io.TerminalWriter() + subprocess.call(args) + tw.line() + tw.sep('#', 'waiting for changes') + tw.line() + + def looponchange(config): newargs = config._origargs[:] - newargs.remove('--looponchange') + if '--looponchange' in newargs: + newargs.remove('--looponchange') + else: + newargs.remove('-f') stats = StatRecorder(config.getini('looponchangeroots')) - command = py.std.functools.partial( - py.std.subprocess.call, [ - py.std.sys.executable, - '-c', SCRIPT % newargs]) + command = py.std.functools.partial(run_once, [ + py.std.sys.executable, '-c', SCRIPT % newargs]) + command() loop_forever(stats, command) return 2 https://bitbucket.org/hpk42/pytest/commits/8614045feec5/ Changeset: 8614045feec5 Branch: merge-cache User: RonnyPfannschmidt Date: 2015-02-26 18:24:42+00:00 Summary: universal wheel Affected #: 1 file diff -r e6a40d65fe5071539fa1ecd07af7f5831504a436 -r 8614045feec5db98c19b2222409d55b446ac8b1b setup.cfg --- a/setup.cfg +++ b/setup.cfg @@ -3,6 +3,9 @@ build-dir = doc/build all_files = 1 +[wheel] +universal = 1 + [upload_sphinx] upload-dir = doc/en/build/html Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 07:27:09 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 06:27:09 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 388 Message-ID: <20150227062708.19170.26092@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/388 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3869:8614045feec5 Author : Ronny Pfannschmidt Branch : merge-cache Message: universal wheel -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 09:52:04 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 08:52:04 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150227085204.29327.54616@app05.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/452d4b637b11/ Changeset: 452d4b637b11 User: hpk42 Date: 2015-02-26 21:02:49+00:00 Summary: fix issue650: introduce new --doctest-ignore-import-errors option courtesy of Charles Cloud. Affected #: 2 files diff -r eeaef9601d3f2996c3bbbc4c0301a859d8bc35b5 -r 452d4b637b11f0fb13da045f64bbd35148a73cda AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -47,3 +47,4 @@ Nicolas Delaby Tom Viner Dave Hunt +Charles Cloud diff -r eeaef9601d3f2996c3bbbc4c0301a859d8bc35b5 -r 452d4b637b11f0fb13da045f64bbd35148a73cda CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,10 @@ - add ability to set command line options by environment variable PYTEST_ADDOPTS. +- fix issue650: new option ``--docttest-ignore-import-errors`` which + will turn import errors in doctests into skips. Thanks Charles Cloud + for the complete PR. + - fix issue655: work around different ways that cause python2/3 to leak sys.exc_info into fixtures/tests causing failures in 3rd party code https://bitbucket.org/hpk42/pytest/commits/15d37e250f68/ Changeset: 15d37e250f68 Branch: issue616 User: hpk42 Date: 2015-02-27 08:51:53+00:00 Summary: move conftest visibility tests and their setup into a class, accomodates @nicoddemus 's comment Affected #: 1 file diff -r 327ead9d7e9b669d1b1a07332b27f46f8fc77d44 -r 15d37e250f681d62e089aa905d5acb0da7b2a30f testing/test_conftest.py --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -259,88 +259,87 @@ """) -# conftest visibility, related to issue616 +class TestConftestVisibility: + def _setup_tree(self, testdir): # for issue616 + # example mostly taken from: + # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html + runner = testdir.mkdir("empty") + package = testdir.mkdir("package") -def _setup_tree(testdir): - # example mostly taken from: - # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html - runner = testdir.mkdir("empty") - package = testdir.mkdir("package") + package.join("conftest.py").write(dedent("""\ + import pytest + @pytest.fixture + def fxtr(): + return "from-package" + """)) + package.join("test_pkgroot.py").write(dedent("""\ + def test_pkgroot(fxtr): + assert fxtr == "from-package" + """)) - package.join("conftest.py").write(dedent("""\ - import pytest - @pytest.fixture - def fxtr(): - return "from-package" - """)) - package.join("test_pkgroot.py").write(dedent("""\ - def test_pkgroot(fxtr): - assert fxtr == "from-package" - """)) + swc = package.mkdir("swc") + swc.join("__init__.py").ensure() + swc.join("conftest.py").write(dedent("""\ + import pytest + @pytest.fixture + def fxtr(): + return "from-swc" + """)) + swc.join("test_with_conftest.py").write(dedent("""\ + def test_with_conftest(fxtr): + assert fxtr == "from-swc" - swc = package.mkdir("swc") - swc.join("__init__.py").ensure() - swc.join("conftest.py").write(dedent("""\ - import pytest - @pytest.fixture - def fxtr(): - return "from-swc" - """)) - swc.join("test_with_conftest.py").write(dedent("""\ - def test_with_conftest(fxtr): - assert fxtr == "from-swc" + """)) - """)) + snc = package.mkdir("snc") + snc.join("__init__.py").ensure() + snc.join("test_no_conftest.py").write(dedent("""\ + def test_no_conftest(fxtr): + assert fxtr == "from-package" # No local conftest.py, so should + # use value from parent dir's - snc = package.mkdir("snc") - snc.join("__init__.py").ensure() - snc.join("test_no_conftest.py").write(dedent("""\ - def test_no_conftest(fxtr): - assert fxtr == "from-package" # No local conftest.py, so should - # use value from parent dir's + """)) + print ("created directory structure:") + for x in testdir.tmpdir.visit(): + print (" " + x.relto(testdir.tmpdir)) - """)) - print ("created directory structure:") - for x in testdir.tmpdir.visit(): - print (" " + x.relto(testdir.tmpdir)) + return { + "runner": runner, + "package": package, + "swc": swc, + "snc": snc} - return { - "runner": runner, - "package": package, - "swc": swc, - "snc": snc} + # 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", [ + ("runner", "..", 3), + ("package", "..", 3), + ("swc", "../..", 3), + ("snc", "../..", 3), -# N.B.: "swc" stands for "subdir with conftest.py" -# "snc" stands for "subdir no [i.e. without] conftest.py" - at pytest.mark.parametrize("chdir,testarg,expect_ntests_passed", [ - ("runner", "..", 3), - ("package", "..", 3), - ("swc", "../..", 3), - ("snc", "../..", 3), + ("runner", "../package", 3), + ("package", ".", 3), + ("swc", "..", 3), + ("snc", "..", 3), - ("runner", "../package", 3), - ("package", ".", 3), - ("swc", "..", 3), - ("snc", "..", 3), + ("runner", "../package/swc", 1), + ("package", "./swc", 1), + ("swc", ".", 1), + ("snc", "../swc", 1), - ("runner", "../package/swc", 1), - ("package", "./swc", 1), - ("swc", ".", 1), - ("snc", "../swc", 1), - - ("runner", "../package/snc", 1), - ("package", "./snc", 1), - ("swc", "../snc", 1), - ("snc", ".", 1), -]) - at pytest.mark.issue616 -def test_parsefactories_relative_node_ids( - testdir, chdir,testarg, expect_ntests_passed): - dirs = _setup_tree(testdir) - print("pytest run in cwd: %s" %( - dirs[chdir].relto(testdir.tmpdir))) - 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) + ("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): + dirs = self._setup_tree(testdir) + print("pytest run in cwd: %s" %( + dirs[chdir].relto(testdir.tmpdir))) + 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) Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 09:59:47 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 08:59:47 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 389 Message-ID: <20150227085947.15312.43310@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/389 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3867:15d37e250f68 Author : holger krekel Branch : issue616 Message: move conftest visibility tests and their setup into a class, accomodates @nicoddemus 's comment -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 11:17:20 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 10:17:20 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: Merged contributing-community into default Message-ID: <20150227101720.28381.45287@app13.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/1abf285d64ae/ Changeset: 1abf285d64ae User: hpk42 Date: 2015-02-27 10:17:14+00:00 Summary: Merged contributing-community into default Affected #: 1 file diff -r 452d4b637b11f0fb13da045f64bbd35148a73cda -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b doc/en/plugins.txt --- a/doc/en/plugins.txt +++ b/doc/en/plugins.txt @@ -1,7 +1,7 @@ .. _plugins: Working with plugins and conftest files -============================================= +======================================= ``pytest`` implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic location types: @@ -16,7 +16,7 @@ .. _`conftest`: conftest.py: local per-directory plugins --------------------------------------------------------------- +---------------------------------------- local ``conftest.py`` plugins contain directory-specific hook implementations. Session and test running activities will @@ -55,7 +55,7 @@ .. _`extplugins`: Installing External Plugins / Searching ------------------------------------------------------- +--------------------------------------- Installing a plugin happens through any usual Python installation tool, for example:: @@ -119,8 +119,42 @@ .. _`available installable plugins`: .. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search + +External plugin development +--------------------------- + +Pytest community cares about pytest users, in particular, it's crucial for the community +to keep all pieces of the pytest ecosystem well supported. External plugins are important for +pytest users, as they implement many useful, and sometimes critical features which the pytest core does +not implement. + +To simplify the plugin development and/or support, it was decided to create teams(companies) on popular code hosting +services (at the moment it's github and bitbucket): + +* ``_: + probably the most popular hosting for pytest plugins + the name ``pytest-dev`` is choosen because ``pytest`` was already taken by + some unknown person, who's not active on the github or just doesn't check the email used to register + that organization. +* ``_: + pytest is hosted on the bitbucket, also a lot of pytest plugins are hosted there. + +More code hosting services can be added in the future. + +Community encourages pytest plugin developers to move their plugins under those organizations (eg transfer ownership), +paying with a better support, faster feedback, better discoverability, etc. + +Generic workflow of the ownership transfer looks like: + +* If not a member already, developer asks for a membership in the `pytest plugin developers community` organizations listed above, sending an email to ``_. + +* Developer transfers the ownership of his plugin repository to the organization listed above. + +* Existing organization members will make sure proper write permissions are set up for developer who transfered the ownership to the organization. + + Writing a plugin by looking at examples ------------------------------------------------------- +--------------------------------------- .. _`Distribute`: http://pypi.python.org/pypi/distribute .. _`setuptools`: http://pypi.python.org/pypi/setuptools @@ -138,7 +172,7 @@ .. _`setuptools entry points`: Making your plugin installable by others ------------------------------------------------ +---------------------------------------- If you want to make your plugin externally available, you may define a so-called entry point for your distribution so @@ -169,10 +203,11 @@ ``myproject.pluginmodule`` as a plugin which can define `well specified hooks`_. + .. _`pluginorder`: Plugin discovery order at tool startup --------------------------------------------- +-------------------------------------- ``pytest`` loads plugin modules at tool startup in the following way: @@ -199,7 +234,7 @@ Requiring/Loading plugins in a test module or conftest file -------------------------------------------------------------- +----------------------------------------------------------- You can require plugins in a test module or a conftest file like this:: @@ -214,7 +249,7 @@ Accessing another plugin by name --------------------------------------------- +-------------------------------- If a plugin wants to collaborate with code from another plugin it can obtain a reference through @@ -230,7 +265,7 @@ .. _`findpluginname`: Finding out which plugins are active ----------------------------------------------------------------------------- +------------------------------------ If you want to find out which plugins are active in your environment you can type:: @@ -244,7 +279,7 @@ .. _`cmdunregister`: Deactivating / unregistering a plugin by name ----------------------------------------------------------------------------- +--------------------------------------------- You can prevent plugins from loading or unregister them:: @@ -257,7 +292,7 @@ .. _`builtin plugins`: pytest default plugin reference -==================================== +=============================== You can find the source code for the following plugins @@ -291,10 +326,10 @@ .. _`well specified hooks`: pytest hook reference -==================================== +===================== Hook specification and validation ------------------------------------------ +--------------------------------- ``pytest`` calls hook functions to implement initialization, running, test execution and reporting. When ``pytest`` loads a plugin it validates @@ -305,7 +340,7 @@ hook name itself you get an error showing the available arguments. Initialization, command line and configuration hooks --------------------------------------------------------------------- +---------------------------------------------------- .. currentmodule:: _pytest.hookspec @@ -319,7 +354,7 @@ .. autofunction:: pytest_unconfigure Generic "runtest" hooks ------------------------------- +----------------------- All runtest related hooks receive a :py:class:`pytest.Item` object. @@ -339,7 +374,7 @@ the reporting hook to print information about a test run. Collection hooks ------------------------------- +---------------- ``pytest`` calls the following hooks for collecting files and directories: @@ -359,7 +394,7 @@ .. autofunction:: pytest_collection_modifyitems Reporting hooks ------------------------------- +--------------- Session related reporting hooks: @@ -375,7 +410,7 @@ Debugging/Interaction hooks --------------------------------------- +--------------------------- There are few hooks which can be used for special reporting or interaction with exceptions: @@ -468,7 +503,7 @@ Reference of objects involved in hooks -=========================================================== +====================================== .. autoclass:: _pytest.config.Config() :members: Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Fri Feb 27 11:17:51 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 10:17:51 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: closebranch Message-ID: <20150227101751.3404.29861@app02.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/0b8989fb033f/ Changeset: 0b8989fb033f Branch: contributing-community User: hpk42 Date: 2015-02-27 10:17:42+00:00 Summary: closebranch Affected #: 0 files Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 11:25:35 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 10:25:35 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 390 Message-ID: <20150227102535.10060.99441@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/390 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3643:0b8989fb033f Author : holger krekel Branch : contributing-community Message: closebranch -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 11:56:20 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 10:56:20 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: added documentationo on the new pytest-dev teams on bitbucket and Message-ID: <20150227105620.7355.19145@app03.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/hpk42/pytest/commits/dc417e256fbe/ Changeset: dc417e256fbe Branch: docs_community User: hpk42 Date: 2015-02-27 10:54:17+00:00 Summary: added documentationo on the new pytest-dev teams on bitbucket and github. See https://pytest.org/latest/contributing.html (tentative) Thanks to Anatoly for pushing and initial work on this. Affected #: 3 files diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,10 @@ - add ability to set command line options by environment variable PYTEST_ADDOPTS. +- added documentationo on the new pytest-dev teams on bitbucket and + github. See https://pytest.org/latest/contributing.html . + Thanks to Anatoly for pushing and initial work on this. + - fix issue650: new option ``--docttest-ignore-import-errors`` which will turn import errors in doctests into skips. Thanks Charles Cloud for the complete PR. diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 CONTRIBUTING.rst --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,18 +1,59 @@ -============ -Contributing -============ +============================ +Contribution getting started +============================ Contributions are highly welcomed and appreciated. Every little help counts, so do not hesitate! +.. contents:: Contribution links + :depth: 2 -Types of contributions -====================== + +.. _submitplugin: + +Submit a plugin, co-develop pytest +---------------------------------- + +Pytest development of the core, some plugins and support code happens +in repositories living under: + +- `the pytest-dev bitbucket team `_ + +- `the pytest-dev github organisation `_ + +All pytest-dev team members have write access to all contained +repositories. pytest core and plugins are generally developed +using `pull requests`_ to respective repositories. + +You can submit your plugin by subscribing to the `pytest-dev mail list +`_ and writing a +mail pointing to your existing pytest plugin repository which must have +the following: + +- PyPI presence with a ``setup.py`` that contains a license, ``pytest-`` + prefixed, version number, authors, short and long description. + +- a ``tox.ini`` for running tests using `tox `_. + +- a ``README.txt`` describing how to use the plugin and on which + platforms it runs. + +- an issue tracker unless you rather want to use the core ``pytest`` + issue tracker. + +If no contributor strongly objects and two agree, the repo will be +transferred to the ``pytest-dev`` organisation and you'll become a +member of the ``pytest-dev`` team, with commit rights to all projects. +We recommend that each plugin has at least three people who have the +right to release to pypi. + + +.. _reportbugs: Report bugs ----------- -Report bugs at https://bitbucket.org/hpk42/pytest/issues. +Report bugs for pytest at https://bitbucket.org/hpk42/pytest/issues If you are reporting a bug, please include: @@ -22,6 +63,8 @@ installed libraries and pytest version. * Detailed steps to reproduce the bug. +.. _submitfeedback: + Submit feedback for developers ------------------------------ @@ -37,6 +80,7 @@ * If you have required skills and/or knowledge, we are very happy for :ref:`pull requests `. +.. _fixbugs: Fix bugs -------- @@ -46,6 +90,8 @@ :ref:`Talk ` to developers to find out how you can fix specific bugs. +.. _writeplugins: + Implement features ------------------ @@ -67,6 +113,7 @@ * Blog posts, articles and such -- they're all very appreciated. .. _pull-requests: +.. _`pull requests`: Preparing Pull Requests on Bitbucket ===================================== @@ -154,7 +201,7 @@ .. _contribution-using-git: -What about git (and so GitHub)? +Using git with bitbucket/hg ------------------------------- There used to be the pytest GitHub mirror. It was removed in favor of the diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 doc/en/plugins.txt --- a/doc/en/plugins.txt +++ b/doc/en/plugins.txt @@ -120,43 +120,9 @@ .. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search -External plugin development ---------------------------- - -Pytest community cares about pytest users, in particular, it's crucial for the community -to keep all pieces of the pytest ecosystem well supported. External plugins are important for -pytest users, as they implement many useful, and sometimes critical features which the pytest core does -not implement. - -To simplify the plugin development and/or support, it was decided to create teams(companies) on popular code hosting -services (at the moment it's github and bitbucket): - -* ``_: - probably the most popular hosting for pytest plugins - the name ``pytest-dev`` is choosen because ``pytest`` was already taken by - some unknown person, who's not active on the github or just doesn't check the email used to register - that organization. -* ``_: - pytest is hosted on the bitbucket, also a lot of pytest plugins are hosted there. - -More code hosting services can be added in the future. - -Community encourages pytest plugin developers to move their plugins under those organizations (eg transfer ownership), -paying with a better support, faster feedback, better discoverability, etc. - -Generic workflow of the ownership transfer looks like: - -* If not a member already, developer asks for a membership in the `pytest plugin developers community` organizations listed above, sending an email to ``_. - -* Developer transfers the ownership of his plugin repository to the organization listed above. - -* Existing organization members will make sure proper write permissions are set up for developer who transfered the ownership to the organization. - - Writing a plugin by looking at examples --------------------------------------- -.. _`Distribute`: http://pypi.python.org/pypi/distribute .. _`setuptools`: http://pypi.python.org/pypi/setuptools If you want to write a plugin, there are many real-life examples @@ -169,6 +135,10 @@ All of these plugins implement the documented `well specified hooks`_ to extend and add functionality. +You can also :doc:`contribute your plugin to pytest-dev` +once it has some happy users other than yourself. + + .. _`setuptools entry points`: Making your plugin installable by others @@ -177,10 +147,10 @@ If you want to make your plugin externally available, you may define a so-called entry point for your distribution so that ``pytest`` finds your plugin module. Entry points are -a feature that is provided by `setuptools`_ or `Distribute`_. -pytest looks up the ``pytest11`` entrypoint to discover its +a feature that is provided by `setuptools`_. pytest looks up +the ``pytest11`` entrypoint to discover its plugins and you can thus make your plugin available by defining -it in your setuptools/distribute-based setup-invocation: +it in your setuptools-invocation: .. sourcecode:: python Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 12:04:42 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 11:04:42 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 391 Message-ID: <20150227110435.16426.16643@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/hpk42/pytest/391 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : 3874:dc417e256fbe Author : holger krekel Branch : docs_community Message: added documentationo on the new pytest-dev teams on bitbucket and -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 12:20:30 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 11:20:30 +0000 Subject: [Pytest-commit] [FAIL] pytest-xdist - # 12 Message-ID: <20150227111942.39419.39878@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest-xdist/12 Project : https://drone.io/bitbucket.org/hpk42/pytest-xdist Repository : https://bitbucket.org/hpk42/pytest-xdist Version : Author : Branch : default Message: -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 12:27:52 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 11:27:52 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: change links to go to the new pytest-dev bitbucket team's repo location Message-ID: <20150227112752.23439.64824@app07.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/26ea4acb80e0/ Changeset: 26ea4acb80e0 Branch: docs_community User: hpk42 Date: 2015-02-27 11:27:40+00:00 Summary: change links to go to the new pytest-dev bitbucket team's repo location Affected #: 14 files diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 CONTRIBUTING.rst --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -53,7 +53,7 @@ Report bugs ----------- -Report bugs for pytest at https://bitbucket.org/hpk42/pytest/issues +Report bugs for pytest at https://bitbucket.org/pytest-dev/pytest/issues If you are reporting a bug, please include: @@ -71,7 +71,7 @@ Do you like pytest? Share some love on Twitter or in your blog posts! We'd also like to hear about your propositions and suggestions. Feel free to -`submit them as issues `__ and: +`submit them as issues `__ and: * Set the "kind" to "enhancement" or "proposal" so that we can quickly find about them. @@ -86,7 +86,7 @@ -------- Look through the BitBucket issues for bugs. Here is sample filter you can use: -https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&kind=bug +https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&kind=bug :ref:`Talk ` to developers to find out how you can fix specific bugs. @@ -97,7 +97,7 @@ Look through the BitBucket issues for enhancements. Here is sample filter you can use: -https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&kind=enhancement +https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&kind=enhancement :ref:`Talk ` to developers to find out how you can implement specific features. @@ -121,7 +121,7 @@ .. note:: What is a "pull request"? It informs project's core developers about the changes you want to review and merge. Pull requests are stored on - `BitBucket servers `__. + `BitBucket servers `__. Once you send pull request, we can discuss it's potential modifications and even add more commits to it later on. @@ -129,7 +129,7 @@ the issues there and submit your pull requests. 1. Fork the - `pytest BitBucket repository `__. It's + `pytest BitBucket repository `__. It's fine to use ``pytest`` as your fork repository name because it will live under your user. @@ -196,7 +196,7 @@ source: YOUR_BITBUCKET_USERNAME/pytest branch: your-branch-name - target: hpk42/pytest + target: pytest-dev/pytest branch: default .. _contribution-using-git: diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 README.rst --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -.. image:: https://drone.io/bitbucket.org/hpk42/pytest/status.png - :target: https://drone.io/bitbucket.org/hpk42/pytest/latest +.. image:: https://drone.io/bitbucket.org/pytest-dev/pytest/status.png + :target: https://drone.io/bitbucket.org/pytest-dev/pytest/latest .. image:: https://pypip.in/v/pytest/badge.png :target: https://pypi.python.org/pypi/pytest @@ -7,9 +7,9 @@ Changelog: http://pytest.org/latest/changelog.html -Issues: https://bitbucket.org/hpk42/pytest/issues?status=open +Issues: https://bitbucket.org/pytest-dev/pytest/issues?status=open -CI: https://drone.io/bitbucket.org/hpk42/pytest +CI: https://drone.io/bitbucket.org/pytest-dev/pytest The ``pytest`` testing tool makes it easy to write small tests, yet scales to support complex functional testing. It provides @@ -44,11 +44,11 @@ and report bugs at: - http://bitbucket.org/hpk42/pytest/issues/ + http://bitbucket.org/pytest-dev/pytest/issues/ and checkout or fork repo at: - http://bitbucket.org/hpk42/pytest/ + http://bitbucket.org/pytest-dev/pytest/ Copyright Holger Krekel and others, 2004-2014 diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1047,7 +1047,7 @@ if ExpectedException is AssertionError: # we want to catch a AssertionError # replace our subclass with the builtin one - # see https://bitbucket.org/hpk42/pytest/issue/176/pytestraises + # see https://bitbucket.org/pytest-dev/pytest/issue/176/pytestraises from _pytest.assertion.util import BuiltinAssertionError \ as ExpectedException msg = ("exceptions must be old-style classes or" diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/adopt.txt --- a/doc/en/adopt.txt +++ b/doc/en/adopt.txt @@ -9,7 +9,7 @@ In 2015 we are trying this for the first time. In February and March we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. -.. _`issue tracker`: https://bitbucket.org/hpk42/pytest/issue/676/adopt-pytest-month-2015 +.. _`issue tracker`: https://bitbucket.org/pytest-dev/pytest/issue/676/adopt-pytest-month-2015 .. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev .. _``: diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/announce/release-2.6.0.txt --- a/doc/en/announce/release-2.6.0.txt +++ b/doc/en/announce/release-2.6.0.txt @@ -21,7 +21,7 @@ Note also that 2.6.0 departs with the "zero reported bugs" policy because it has been too hard to keep up with it, unfortunately. Instead we are for now rather bound to work on "upvoted" issues in -the https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&sort=-votes +the https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&sort=-votes issue tracker. See docs at: diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/contact.txt --- a/doc/en/contact.txt +++ b/doc/en/contact.txt @@ -29,7 +29,7 @@ - `merlinux.eu`_ offers pytest and tox-related professional teaching and consulting. -.. _`pytest issue tracker`: http://bitbucket.org/hpk42/pytest/issues/ +.. _`pytest issue tracker`: http://bitbucket.org/pytest-dev/pytest/issues/ .. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/ .. _`merlinux.eu`: http://merlinux.eu diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/nose.txt --- a/doc/en/nose.txt +++ b/doc/en/nose.txt @@ -39,13 +39,13 @@ it doesn't seem useful to duplicate the unittest-API like nose does. If you however rather think pytest should support the unittest-spelling on plain classes please post `to this issue - `_. + `_. - nose imports test modules with the same import path (e.g. ``tests.test_mod``) but different file system paths (e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``) by extending sys.path/import semantics. pytest does not do that - but there is discussion in `issue268 `_ for adding some support. Note that + but there is discussion in `issue268 `_ for adding some support. Note that `nose2 choose to avoid this sys.path/import hackery `_. - nose-style doctests are not collected and executed correctly, diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/plugins.txt --- a/doc/en/plugins.txt +++ b/doc/en/plugins.txt @@ -9,7 +9,7 @@ * `external plugins`_: modules discovered through `setuptools entry points`_ * `conftest.py plugins`_: modules auto-discovered in test directories -.. _`pytest/plugin`: http://bitbucket.org/hpk42/pytest/src/tip/pytest/plugin/ +.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/ .. _`conftest.py plugins`: .. _`conftest.py`: .. _`localplugin`: @@ -266,7 +266,7 @@ You can find the source code for the following plugins -in the `pytest repository `_. +in the `pytest repository `_. .. autosummary:: @@ -405,7 +405,7 @@ For an example, see `newhooks.py`_ from :ref:`xdist`. -.. _`newhooks.py`: https://bitbucket.org/hpk42/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default +.. _`newhooks.py`: https://bitbucket.org/pytest-dev/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default Using hooks from 3rd party plugins diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/plugins_index/index.txt --- a/doc/en/plugins_index/index.txt +++ b/doc/en/plugins_index/index.txt @@ -30,7 +30,7 @@ `pytest-bugzilla `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test bugzilla integration plugin :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nibrahim/pytest_bugzilla `pytest-cache `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-cache/ + :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-cache/ `pytest-capturelog `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to capture log messages :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/memedough/pytest-capturelog/overview `pytest-codecheckers `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends) @@ -64,7 +64,7 @@ `pytest-eradicate `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check for commented out code :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/spil-johan/pytest-eradicate `pytest-figleaf `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test figleaf coverage plugin - :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-figleaf + :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-figleaf `pytest-fixture-tools `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 ? Plugin for pytest which provides tools for fixtures :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 `pytest-flakes `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check source code with pyflakes @@ -114,7 +114,7 @@ `pytest-paste-config `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 ? Allow setting the path to a paste config file :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 `pytest-pep8 `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to check PEP8 requirements - :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-pep8/ + :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-pep8/ `pytest-pipeline `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bow/pytest_pipeline `pytest-poo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Visualize your crappy tests @@ -158,9 +158,9 @@ `pytest-twisted `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A twisted plugin for py.test. :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/schmir/pytest-twisted `pytest-xdist `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes - :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-xdist + :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xdist `pytest-xprocess `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to manage external processes across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-xprocess/ + :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xprocess/ `pytest-yamlwsgi `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 ? Run tests against wsgi apps defined in yaml :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 `pytest-zap `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png OWASP ZAP plugin for py.test. diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/status.txt --- a/doc/en/status.txt +++ b/doc/en/status.txt @@ -1,5 +1,5 @@ pytest development status ================================ -https://drone.io/bitbucket.org/hpk42/pytest +https://drone.io/bitbucket.org/pytest-dev/pytest diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/talks.txt --- a/doc/en/talks.txt +++ b/doc/en/talks.txt @@ -11,8 +11,8 @@ Talks and blog postings --------------------------------------------- -.. _`tutorial1 repository`: http://bitbucket.org/hpk42/pytest-tutorial1/ -.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/hpk42/pytest-tutorial1/raw/tip/pytest-basic.pdf +.. _`tutorial1 repository`: http://bitbucket.org/pytest-dev/pytest-tutorial1/ +.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/pytest-dev/pytest-tutorial1/raw/tip/pytest-basic.pdf - `Introduction to pytest, Andreas Pelme, EuroPython 2014 `_. diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 doc/en/xdist.txt --- a/doc/en/xdist.txt +++ b/doc/en/xdist.txt @@ -192,6 +192,6 @@ where the configuration file was found. .. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist -.. _`pytest-xdist repository`: http://bitbucket.org/hpk42/pytest-xdist +.. _`pytest-xdist repository`: http://bitbucket.org/pytest-dev/pytest-xdist .. _`pytest`: http://pytest.org diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 extra/get_issues.py --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -2,7 +2,7 @@ import py import textwrap -issues_url = "http://bitbucket.org/api/1.0/repositories/hpk42/pytest/issues" +issues_url = "http://bitbucket.org/api/1.0/repositories/pytest-dev/pytest/issues" import requests @@ -53,7 +53,7 @@ kind = metadata["kind"] status = issue["status"] id = issue["local_id"] - link = "https://bitbucket.org/hpk42/pytest/issue/%s/" % id + link = "https://bitbucket.org/pytest-dev/pytest/issue/%s/" % id print("----") print(status, kind, link) print(title) diff -r dc417e256fbe08ec5e838e48c6b6caba06ebe331 -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 testing/test_capture.py --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1040,7 +1040,7 @@ def test_pickling_and_unpickling_enocded_file(): - # See https://bitbucket.org/hpk42/pytest/pull-request/194 + # See https://bitbucket.org/pytest-dev/pytest/pull-request/194 # pickle.loads() raises infinite recursion if # EncodedFile.__getattr__ is not implemented properly ef = capture.EncodedFile(None, None) Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 12:27:54 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 11:27:54 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 392 Message-ID: <20150227112754.10060.8521@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/392 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : Author : Branch : docs_community Message: -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 12:58:49 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 11:58:49 -0000 Subject: [Pytest-commit] commit/pytest: 3 new changesets Message-ID: <20150227115849.25096.1281@app01.ash-private.bitbucket.org> 3 new commits in pytest: https://bitbucket.org/pytest-dev/pytest/commits/cb888d5d8876/ Changeset: cb888d5d8876 Branch: pytest-2.6 User: hpk42 Date: 2015-02-27 11:32:53+00:00 Summary: modify links to go to new pytest-dev organisation Affected #: 1 file diff -r f03b6de8325f5b6c35cea7c3de092f134ea8ef07 -r cb888d5d88763016b0d58a21df636afbdb33305d README.rst --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -.. image:: https://drone.io/bitbucket.org/hpk42/pytest/status.png - :target: https://drone.io/bitbucket.org/hpk42/pytest/latest +.. image:: https://drone.io/bitbucket.org/pytest-dev/pytest/status.png + :target: https://drone.io/bitbucket.org/pytest-dev/pytest/latest .. image:: https://pypip.in/v/pytest/badge.png :target: https://crate.io/packages/pytest/ @@ -7,9 +7,9 @@ Changelog: http://pytest.org/latest/changelog.html -Issues: https://bitbucket.org/hpk42/pytest/issues?status=open +Issues: https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open -CI: https://drone.io/bitbucket.org/hpk42/pytest +CI: https://drone.io/bitbucket.org/pytest-dev/pytest The ``pytest`` testing tool makes it easy to write small tests, yet scales to support complex functional testing. It provides @@ -44,11 +44,11 @@ and report bugs at: - http://bitbucket.org/hpk42/pytest/issues/ + http://bitbucket.org/pytest-dev/pytest/issues/ and checkout or fork repo at: - http://bitbucket.org/hpk42/pytest/ + http://bitbucket.org/pytest-dev/pytest/ Copyright Holger Krekel and others, 2004-2014 https://bitbucket.org/pytest-dev/pytest/commits/8caa7ffdce29/ Changeset: 8caa7ffdce29 Branch: flake8-clean User: hpk42 Date: 2015-02-27 11:33:24+00:00 Summary: closebranch Affected #: 0 files https://bitbucket.org/pytest-dev/pytest/commits/c724e3e1f9e6/ Changeset: c724e3e1f9e6 Branch: docs_community User: hpk42 Date: 2015-02-27 11:53:14+00:00 Summary: switch to push to latest docs, because otherwise people get misled to old repos which don't exist anymore Affected #: 1 file diff -r 26ea4acb80e0879bdbac7994c3f9cedb13a84821 -r c724e3e1f9e6d582db7c77dc15defdf6234e98c3 doc/en/Makefile --- a/doc/en/Makefile +++ b/doc/en/Makefile @@ -42,7 +42,7 @@ clean: -rm -rf $(BUILDDIR)/* -SITETARGET=dev +SITETARGET=latest install: html # for access talk to someone with login rights to Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 12:58:51 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 11:58:51 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 393 Message-ID: <20150227115850.39405.17206@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/393 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : Author : Branch : docs_community Message: -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 13:38:59 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 12:38:59 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: fix typos, clarify git/hg Message-ID: <20150227123859.16423.99192@app03.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/d63f0898c27a/ Changeset: d63f0898c27a Branch: docs_community User: hpk42 Date: 2015-02-27 12:38:45+00:00 Summary: fix typos, clarify git/hg Affected #: 2 files diff -r c724e3e1f9e6d582db7c77dc15defdf6234e98c3 -r d63f0898c27a4253e87feeedfbd8f4c85acc72a0 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,7 @@ - add ability to set command line options by environment variable PYTEST_ADDOPTS. -- added documentationo on the new pytest-dev teams on bitbucket and +- added documentation on the new pytest-dev teams on bitbucket and github. See https://pytest.org/latest/contributing.html . Thanks to Anatoly for pushing and initial work on this. diff -r c724e3e1f9e6d582db7c77dc15defdf6234e98c3 -r d63f0898c27a4253e87feeedfbd8f4c85acc72a0 CONTRIBUTING.rst --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -209,10 +209,10 @@ put their issues and pull requests. Also it wasn't easily possible to automate the mirroring process. -However, it's still possible to use git to contribute to pytest using tools -like `gitifyhg `_ which allows you to -clone and work with Mercurial repo still using git. +In general we recommend to work with the same version control system of the +original repository. If you insist on using git with bitbucket/hg you +may try `gitifyhg `_ but are on your +own and need to submit pull requests through the respective platform, +nevertheless. -.. warning:: - Remember that git is **not** a default version control system for pytest and - you need to be careful using it. + Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 13:39:03 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 12:39:03 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 394 Message-ID: <20150227123902.87093.4152@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/394 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : Author : Branch : docs_community Message: -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 14:58:32 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 13:58:32 -0000 Subject: [Pytest-commit] commit/pytest: bubenkoff: Merged in docs_community (pull request #254) Message-ID: <20150227135832.12860.73347@app01.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/de09a4c6bc60/ Changeset: de09a4c6bc60 User: bubenkoff Date: 2015-02-27 13:58:27+00:00 Summary: Merged in docs_community (pull request #254) added documentationo on the new pytest-dev teams on bitbucket and Affected #: 16 files diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,10 @@ - add ability to set command line options by environment variable PYTEST_ADDOPTS. +- added documentation on the new pytest-dev teams on bitbucket and + github. See https://pytest.org/latest/contributing.html . + Thanks to Anatoly for pushing and initial work on this. + - fix issue650: new option ``--docttest-ignore-import-errors`` which will turn import errors in doctests into skips. Thanks Charles Cloud for the complete PR. diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b CONTRIBUTING.rst --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,18 +1,59 @@ -============ -Contributing -============ +============================ +Contribution getting started +============================ Contributions are highly welcomed and appreciated. Every little help counts, so do not hesitate! +.. contents:: Contribution links + :depth: 2 -Types of contributions -====================== + +.. _submitplugin: + +Submit a plugin, co-develop pytest +---------------------------------- + +Pytest development of the core, some plugins and support code happens +in repositories living under: + +- `the pytest-dev bitbucket team `_ + +- `the pytest-dev github organisation `_ + +All pytest-dev team members have write access to all contained +repositories. pytest core and plugins are generally developed +using `pull requests`_ to respective repositories. + +You can submit your plugin by subscribing to the `pytest-dev mail list +`_ and writing a +mail pointing to your existing pytest plugin repository which must have +the following: + +- PyPI presence with a ``setup.py`` that contains a license, ``pytest-`` + prefixed, version number, authors, short and long description. + +- a ``tox.ini`` for running tests using `tox `_. + +- a ``README.txt`` describing how to use the plugin and on which + platforms it runs. + +- an issue tracker unless you rather want to use the core ``pytest`` + issue tracker. + +If no contributor strongly objects and two agree, the repo will be +transferred to the ``pytest-dev`` organisation and you'll become a +member of the ``pytest-dev`` team, with commit rights to all projects. +We recommend that each plugin has at least three people who have the +right to release to pypi. + + +.. _reportbugs: Report bugs ----------- -Report bugs at https://bitbucket.org/hpk42/pytest/issues. +Report bugs for pytest at https://bitbucket.org/pytest-dev/pytest/issues If you are reporting a bug, please include: @@ -22,13 +63,15 @@ installed libraries and pytest version. * Detailed steps to reproduce the bug. +.. _submitfeedback: + Submit feedback for developers ------------------------------ Do you like pytest? Share some love on Twitter or in your blog posts! We'd also like to hear about your propositions and suggestions. Feel free to -`submit them as issues `__ and: +`submit them as issues `__ and: * Set the "kind" to "enhancement" or "proposal" so that we can quickly find about them. @@ -37,21 +80,24 @@ * If you have required skills and/or knowledge, we are very happy for :ref:`pull requests `. +.. _fixbugs: Fix bugs -------- Look through the BitBucket issues for bugs. Here is sample filter you can use: -https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&kind=bug +https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&kind=bug :ref:`Talk ` to developers to find out how you can fix specific bugs. +.. _writeplugins: + Implement features ------------------ Look through the BitBucket issues for enhancements. Here is sample filter you can use: -https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&kind=enhancement +https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&kind=enhancement :ref:`Talk ` to developers to find out how you can implement specific features. @@ -67,6 +113,7 @@ * Blog posts, articles and such -- they're all very appreciated. .. _pull-requests: +.. _`pull requests`: Preparing Pull Requests on Bitbucket ===================================== @@ -74,7 +121,7 @@ .. note:: What is a "pull request"? It informs project's core developers about the changes you want to review and merge. Pull requests are stored on - `BitBucket servers `__. + `BitBucket servers `__. Once you send pull request, we can discuss it's potential modifications and even add more commits to it later on. @@ -82,7 +129,7 @@ the issues there and submit your pull requests. 1. Fork the - `pytest BitBucket repository `__. It's + `pytest BitBucket repository `__. It's fine to use ``pytest`` as your fork repository name because it will live under your user. @@ -149,12 +196,12 @@ source: YOUR_BITBUCKET_USERNAME/pytest branch: your-branch-name - target: hpk42/pytest + target: pytest-dev/pytest branch: default .. _contribution-using-git: -What about git (and so GitHub)? +Using git with bitbucket/hg ------------------------------- There used to be the pytest GitHub mirror. It was removed in favor of the @@ -162,10 +209,10 @@ put their issues and pull requests. Also it wasn't easily possible to automate the mirroring process. -However, it's still possible to use git to contribute to pytest using tools -like `gitifyhg `_ which allows you to -clone and work with Mercurial repo still using git. +In general we recommend to work with the same version control system of the +original repository. If you insist on using git with bitbucket/hg you +may try `gitifyhg `_ but are on your +own and need to submit pull requests through the respective platform, +nevertheless. -.. warning:: - Remember that git is **not** a default version control system for pytest and - you need to be careful using it. + diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b README.rst --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -.. image:: https://drone.io/bitbucket.org/hpk42/pytest/status.png - :target: https://drone.io/bitbucket.org/hpk42/pytest/latest +.. image:: https://drone.io/bitbucket.org/pytest-dev/pytest/status.png + :target: https://drone.io/bitbucket.org/pytest-dev/pytest/latest .. image:: https://pypip.in/v/pytest/badge.png :target: https://pypi.python.org/pypi/pytest @@ -7,9 +7,9 @@ Changelog: http://pytest.org/latest/changelog.html -Issues: https://bitbucket.org/hpk42/pytest/issues?status=open +Issues: https://bitbucket.org/pytest-dev/pytest/issues?status=open -CI: https://drone.io/bitbucket.org/hpk42/pytest +CI: https://drone.io/bitbucket.org/pytest-dev/pytest The ``pytest`` testing tool makes it easy to write small tests, yet scales to support complex functional testing. It provides @@ -44,11 +44,11 @@ and report bugs at: - http://bitbucket.org/hpk42/pytest/issues/ + http://bitbucket.org/pytest-dev/pytest/issues/ and checkout or fork repo at: - http://bitbucket.org/hpk42/pytest/ + http://bitbucket.org/pytest-dev/pytest/ Copyright Holger Krekel and others, 2004-2014 diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1047,7 +1047,7 @@ if ExpectedException is AssertionError: # we want to catch a AssertionError # replace our subclass with the builtin one - # see https://bitbucket.org/hpk42/pytest/issue/176/pytestraises + # see https://bitbucket.org/pytest-dev/pytest/issue/176/pytestraises from _pytest.assertion.util import BuiltinAssertionError \ as ExpectedException msg = ("exceptions must be old-style classes or" diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/Makefile --- a/doc/en/Makefile +++ b/doc/en/Makefile @@ -42,7 +42,7 @@ clean: -rm -rf $(BUILDDIR)/* -SITETARGET=dev +SITETARGET=latest install: html # for access talk to someone with login rights to diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/adopt.txt --- a/doc/en/adopt.txt +++ b/doc/en/adopt.txt @@ -9,7 +9,7 @@ In 2015 we are trying this for the first time. In February and March we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. -.. _`issue tracker`: https://bitbucket.org/hpk42/pytest/issue/676/adopt-pytest-month-2015 +.. _`issue tracker`: https://bitbucket.org/pytest-dev/pytest/issue/676/adopt-pytest-month-2015 .. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev .. _``: diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/announce/release-2.6.0.txt --- a/doc/en/announce/release-2.6.0.txt +++ b/doc/en/announce/release-2.6.0.txt @@ -21,7 +21,7 @@ Note also that 2.6.0 departs with the "zero reported bugs" policy because it has been too hard to keep up with it, unfortunately. Instead we are for now rather bound to work on "upvoted" issues in -the https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&sort=-votes +the https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&sort=-votes issue tracker. See docs at: diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/contact.txt --- a/doc/en/contact.txt +++ b/doc/en/contact.txt @@ -29,7 +29,7 @@ - `merlinux.eu`_ offers pytest and tox-related professional teaching and consulting. -.. _`pytest issue tracker`: http://bitbucket.org/hpk42/pytest/issues/ +.. _`pytest issue tracker`: http://bitbucket.org/pytest-dev/pytest/issues/ .. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/ .. _`merlinux.eu`: http://merlinux.eu diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/nose.txt --- a/doc/en/nose.txt +++ b/doc/en/nose.txt @@ -39,13 +39,13 @@ it doesn't seem useful to duplicate the unittest-API like nose does. If you however rather think pytest should support the unittest-spelling on plain classes please post `to this issue - `_. + `_. - nose imports test modules with the same import path (e.g. ``tests.test_mod``) but different file system paths (e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``) by extending sys.path/import semantics. pytest does not do that - but there is discussion in `issue268 `_ for adding some support. Note that + but there is discussion in `issue268 `_ for adding some support. Note that `nose2 choose to avoid this sys.path/import hackery `_. - nose-style doctests are not collected and executed correctly, diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/plugins.txt --- a/doc/en/plugins.txt +++ b/doc/en/plugins.txt @@ -9,7 +9,7 @@ * `external plugins`_: modules discovered through `setuptools entry points`_ * `conftest.py plugins`_: modules auto-discovered in test directories -.. _`pytest/plugin`: http://bitbucket.org/hpk42/pytest/src/tip/pytest/plugin/ +.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/ .. _`conftest.py plugins`: .. _`conftest.py`: .. _`localplugin`: @@ -120,43 +120,9 @@ .. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search -External plugin development ---------------------------- - -Pytest community cares about pytest users, in particular, it's crucial for the community -to keep all pieces of the pytest ecosystem well supported. External plugins are important for -pytest users, as they implement many useful, and sometimes critical features which the pytest core does -not implement. - -To simplify the plugin development and/or support, it was decided to create teams(companies) on popular code hosting -services (at the moment it's github and bitbucket): - -* ``_: - probably the most popular hosting for pytest plugins - the name ``pytest-dev`` is choosen because ``pytest`` was already taken by - some unknown person, who's not active on the github or just doesn't check the email used to register - that organization. -* ``_: - pytest is hosted on the bitbucket, also a lot of pytest plugins are hosted there. - -More code hosting services can be added in the future. - -Community encourages pytest plugin developers to move their plugins under those organizations (eg transfer ownership), -paying with a better support, faster feedback, better discoverability, etc. - -Generic workflow of the ownership transfer looks like: - -* If not a member already, developer asks for a membership in the `pytest plugin developers community` organizations listed above, sending an email to ``_. - -* Developer transfers the ownership of his plugin repository to the organization listed above. - -* Existing organization members will make sure proper write permissions are set up for developer who transfered the ownership to the organization. - - Writing a plugin by looking at examples --------------------------------------- -.. _`Distribute`: http://pypi.python.org/pypi/distribute .. _`setuptools`: http://pypi.python.org/pypi/setuptools If you want to write a plugin, there are many real-life examples @@ -169,6 +135,10 @@ All of these plugins implement the documented `well specified hooks`_ to extend and add functionality. +You can also :doc:`contribute your plugin to pytest-dev` +once it has some happy users other than yourself. + + .. _`setuptools entry points`: Making your plugin installable by others @@ -177,10 +147,10 @@ If you want to make your plugin externally available, you may define a so-called entry point for your distribution so that ``pytest`` finds your plugin module. Entry points are -a feature that is provided by `setuptools`_ or `Distribute`_. -pytest looks up the ``pytest11`` entrypoint to discover its +a feature that is provided by `setuptools`_. pytest looks up +the ``pytest11`` entrypoint to discover its plugins and you can thus make your plugin available by defining -it in your setuptools/distribute-based setup-invocation: +it in your setuptools-invocation: .. sourcecode:: python @@ -296,7 +266,7 @@ You can find the source code for the following plugins -in the `pytest repository `_. +in the `pytest repository `_. .. autosummary:: @@ -435,7 +405,7 @@ For an example, see `newhooks.py`_ from :ref:`xdist`. -.. _`newhooks.py`: https://bitbucket.org/hpk42/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default +.. _`newhooks.py`: https://bitbucket.org/pytest-dev/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default Using hooks from 3rd party plugins diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/plugins_index/index.txt --- a/doc/en/plugins_index/index.txt +++ b/doc/en/plugins_index/index.txt @@ -30,7 +30,7 @@ `pytest-bugzilla `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test bugzilla integration plugin :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nibrahim/pytest_bugzilla `pytest-cache `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-cache/ + :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-cache/ `pytest-capturelog `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to capture log messages :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/memedough/pytest-capturelog/overview `pytest-codecheckers `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends) @@ -64,7 +64,7 @@ `pytest-eradicate `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check for commented out code :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/spil-johan/pytest-eradicate `pytest-figleaf `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test figleaf coverage plugin - :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-figleaf + :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-figleaf `pytest-fixture-tools `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 ? Plugin for pytest which provides tools for fixtures :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 `pytest-flakes `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check source code with pyflakes @@ -114,7 +114,7 @@ `pytest-paste-config `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 ? Allow setting the path to a paste config file :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 `pytest-pep8 `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to check PEP8 requirements - :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-pep8/ + :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-pep8/ `pytest-pipeline `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bow/pytest_pipeline `pytest-poo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Visualize your crappy tests @@ -158,9 +158,9 @@ `pytest-twisted `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A twisted plugin for py.test. :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/schmir/pytest-twisted `pytest-xdist `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes - :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-xdist + :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xdist `pytest-xprocess `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to manage external processes across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hpk42/pytest-xprocess/ + :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xprocess/ `pytest-yamlwsgi `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 ? Run tests against wsgi apps defined in yaml :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 `pytest-zap `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png OWASP ZAP plugin for py.test. diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/status.txt --- a/doc/en/status.txt +++ b/doc/en/status.txt @@ -1,5 +1,5 @@ pytest development status ================================ -https://drone.io/bitbucket.org/hpk42/pytest +https://drone.io/bitbucket.org/pytest-dev/pytest diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/talks.txt --- a/doc/en/talks.txt +++ b/doc/en/talks.txt @@ -11,8 +11,8 @@ Talks and blog postings --------------------------------------------- -.. _`tutorial1 repository`: http://bitbucket.org/hpk42/pytest-tutorial1/ -.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/hpk42/pytest-tutorial1/raw/tip/pytest-basic.pdf +.. _`tutorial1 repository`: http://bitbucket.org/pytest-dev/pytest-tutorial1/ +.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/pytest-dev/pytest-tutorial1/raw/tip/pytest-basic.pdf - `Introduction to pytest, Andreas Pelme, EuroPython 2014 `_. diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b doc/en/xdist.txt --- a/doc/en/xdist.txt +++ b/doc/en/xdist.txt @@ -192,6 +192,6 @@ where the configuration file was found. .. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist -.. _`pytest-xdist repository`: http://bitbucket.org/hpk42/pytest-xdist +.. _`pytest-xdist repository`: http://bitbucket.org/pytest-dev/pytest-xdist .. _`pytest`: http://pytest.org diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b extra/get_issues.py --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -2,7 +2,7 @@ import py import textwrap -issues_url = "http://bitbucket.org/api/1.0/repositories/hpk42/pytest/issues" +issues_url = "http://bitbucket.org/api/1.0/repositories/pytest-dev/pytest/issues" import requests @@ -53,7 +53,7 @@ kind = metadata["kind"] status = issue["status"] id = issue["local_id"] - link = "https://bitbucket.org/hpk42/pytest/issue/%s/" % id + link = "https://bitbucket.org/pytest-dev/pytest/issue/%s/" % id print("----") print(status, kind, link) print(title) diff -r 1abf285d64ae7fcfaee1fcd01c045357a8a7411b -r de09a4c6bc60c27686245e705947439270e2c69b testing/test_capture.py --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1040,7 +1040,7 @@ def test_pickling_and_unpickling_enocded_file(): - # See https://bitbucket.org/hpk42/pytest/pull-request/194 + # See https://bitbucket.org/pytest-dev/pytest/pull-request/194 # pickle.loads() raises infinite recursion if # EncodedFile.__getattr__ is not implemented properly ef = capture.EncodedFile(None, None) Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Fri Feb 27 14:58:33 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 13:58:33 -0000 Subject: [Pytest-commit] commit/pytest: bubenkoff: Close branch docs_community Message-ID: <20150227135833.7860.54406@app08.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/4872bc390b28/ Changeset: 4872bc390b28 Branch: docs_community User: bubenkoff Date: 2015-02-27 13:58:27+00:00 Summary: Close branch docs_community Affected #: 0 files Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 14:59:29 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 13:59:29 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 395 Message-ID: <20150227135836.77540.97232@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/395 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : Author : Branch : docs_community Message: -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 15:12:24 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 14:12:24 -0000 Subject: [Pytest-commit] commit/pytest: gutworth: another update for get_issues.py to account for repository move Message-ID: <20150227141224.29847.60616@app14.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/8a4edb605b1e/ Changeset: 8a4edb605b1e Branch: update-issues User: gutworth Date: 2015-02-27 14:12:00+00:00 Summary: another update for get_issues.py to account for repository move Affected #: 1 file diff -r de09a4c6bc60c27686245e705947439270e2c69b -r 8a4edb605b1e41b6cef435bda487bd0a825c3d66 extra/get_issues.py --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -11,7 +11,7 @@ start = 0 issues = [] while 1: - post_data = {"accountname": "hpk42", + post_data = {"accountname": "pytest-dev", "repo_slug": "pytest", "start": start, "limit": chunksize} Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 15:12:40 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 14:12:40 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 396 Message-ID: <20150227141227.87097.45300@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/396 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : Author : Branch : update-issues Message: -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Fri Feb 27 15:32:17 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 14:32:17 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: Merged in update-issues (pull request #255) Message-ID: <20150227143217.16608.49434@app06.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/760135a7438a/ Changeset: 760135a7438a User: hpk42 Date: 2015-02-27 14:32:13+00:00 Summary: Merged in update-issues (pull request #255) another update for get_issues.py to account for repository move Affected #: 1 file diff -r de09a4c6bc60c27686245e705947439270e2c69b -r 760135a7438a89f8f80ba29832b9e3e93f23b587 extra/get_issues.py --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -11,7 +11,7 @@ start = 0 issues = [] while 1: - post_data = {"accountname": "hpk42", + post_data = {"accountname": "pytest-dev", "repo_slug": "pytest", "start": start, "limit": chunksize} Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Fri Feb 27 15:34:42 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 14:34:42 -0000 Subject: [Pytest-commit] commit/pytest: 2 new changesets Message-ID: <20150227143442.28361.27365@app06.ash-private.bitbucket.org> 2 new commits in pytest: https://bitbucket.org/pytest-dev/pytest/commits/10327a5aa2ac/ Changeset: 10327a5aa2ac Branch: update-issues User: gutworth Date: 2015-02-27 14:34:16+00:00 Summary: close branch Affected #: 0 files https://bitbucket.org/pytest-dev/pytest/commits/211045e4cb73/ Changeset: 211045e4cb73 User: gutworth Date: 2015-02-27 14:34:33+00:00 Summary: merge dead branch Affected #: 0 files Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Fri Feb 27 15:55:35 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 14:55:35 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: make "Adopt pytest" note more prominent, fix link from plugins page. Message-ID: <20150227145535.24669.40347@app13.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/762ed0a37f1e/ Changeset: 762ed0a37f1e User: hpk42 Date: 2015-02-27 14:49:25+00:00 Summary: make "Adopt pytest" note more prominent, fix link from plugins page. Affected #: 2 files diff -r 211045e4cb73b228f4b78336ffa966339616842b -r 762ed0a37f1e0eac9724ad323fb26d47c0bd9616 doc/en/index.txt --- a/doc/en/index.txt +++ b/doc/en/index.txt @@ -1,7 +1,8 @@ .. _features: +.. note:: - Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? April 2015 is `adopt pytest month`_! + Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? **April 2015** is `adopt pytest month`_! .. _`adopt pytest month`: adopt.html diff -r 211045e4cb73b228f4b78336ffa966339616842b -r 762ed0a37f1e0eac9724ad323fb26d47c0bd9616 doc/en/plugins.txt --- a/doc/en/plugins.txt +++ b/doc/en/plugins.txt @@ -135,7 +135,7 @@ All of these plugins implement the documented `well specified hooks`_ to extend and add functionality. -You can also :doc:`contribute your plugin to pytest-dev` +You can also :ref:`contribute your plugin to pytest-dev` once it has some happy users other than yourself. Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Fri Feb 27 16:42:21 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 15:42:21 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: a few more fixes Message-ID: <20150227154221.24038.59462@app05.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/f7f076b07d10/ Changeset: f7f076b07d10 User: hpk42 Date: 2015-02-27 15:42:03+00:00 Summary: a few more fixes Affected #: 2 files diff -r 762ed0a37f1e0eac9724ad323fb26d47c0bd9616 -r f7f076b07d105d2fceeb38c998910be33f9fe290 CONTRIBUTING.rst --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -112,11 +112,11 @@ * Docstrings. There's never too much of them. * Blog posts, articles and such -- they're all very appreciated. +.. _`pull requests`: .. _pull-requests: -.. _`pull requests`: Preparing Pull Requests on Bitbucket -===================================== +------------------------------------ .. note:: What is a "pull request"? It informs project's core developers about the diff -r 762ed0a37f1e0eac9724ad323fb26d47c0bd9616 -r f7f076b07d105d2fceeb38c998910be33f9fe290 doc/en/adopt.txt --- a/doc/en/adopt.txt +++ b/doc/en/adopt.txt @@ -1,12 +1,12 @@ -April is "adopt pytest month" +April 2015 is "adopt pytest month" ============================================= Are you an enthusiastic pytest user, the local testing guru in your workplace? Or are you considering using pytest for your open source project, but not sure how to get started? Then you may be interested in "adopt pytest month"! We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest. -In 2015 we are trying this for the first time. In February and March we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. +In 2015 we are trying this for the first time. In February and March 2015 we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. .. _`issue tracker`: https://bitbucket.org/pytest-dev/pytest/issue/676/adopt-pytest-month-2015 Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Fri Feb 27 17:40:47 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Fri, 27 Feb 2015 16:40:47 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: take in a unpolished copy of the base cache documentation Message-ID: <20150227164047.26851.70478@app01.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/aa0dc8752409/ Changeset: aa0dc8752409 Branch: merge-cache User: RonnyPfannschmidt Date: 2015-02-27 16:40:18+00:00 Summary: take in a unpolished copy of the base cache documentation Affected #: 2 files diff -r 8614045feec5db98c19b2222409d55b446ac8b1b -r aa0dc8752409f064fa6414289f2c8b19e9aa1b14 doc/en/apiref.txt --- a/doc/en/apiref.txt +++ b/doc/en/apiref.txt @@ -24,4 +24,5 @@ unittest.txt nose.txt doctest.txt + cache.txt diff -r 8614045feec5db98c19b2222409d55b446ac8b1b -r aa0dc8752409f064fa6414289f2c8b19e9aa1b14 doc/en/cache.txt --- /dev/null +++ b/doc/en/cache.txt @@ -0,0 +1,270 @@ +pytest-cache: working with cross-testrun state +===================================================== + +Usage +--------- + +Install via:: + + pip install pytest-cache + +after which other plugins can access a new `config.cache`_ object +which helps sharing values between ``py.test`` invocations. + +The plugin provides two options to rerun failures, namely: + +* ``--lf`` (last failures) - to only re-run the failures. + +* ``--ff`` (failures first) - to run the failures first and then the rest of + the tests. + +For cleanup (usually not needed), a ``--clearcache`` option allows to remove +all cross-session cache contents ahead of a test run. + + +Rerunning only failures or failures first +----------------------------------------------- + +First, let's create 50 test invocation of which only 2 fail:: + + # content of test_50.py + import pytest + + @pytest.mark.parametrize("i", range(50)) + def test_num(i): + if i in (17,25): + pytest.fail("bad luck") + +If you run this for the first time you will see two failures:: + + $ py.test -q + .................F.......F........................ + =================================== FAILURES =================================== + _________________________________ test_num[17] _________________________________ + + i = 17 + + @pytest.mark.parametrize("i", range(50)) + def test_num(i): + if i in (17,25): + > pytest.fail("bad luck") + E Failed: bad luck + + test_50.py:6: Failed + _________________________________ test_num[25] _________________________________ + + i = 25 + + @pytest.mark.parametrize("i", range(50)) + def test_num(i): + if i in (17,25): + > pytest.fail("bad luck") + E Failed: bad luck + + test_50.py:6: Failed + +If you then run it with ``--lf`` you will run only the two failing test +from the last run:: + + $ py.test --lf + ============================= test session starts ============================== + platform linux2 -- Python 2.7.3 -- pytest-2.3.5 + run-last-failure: rerun last 2 failures + plugins: cache + collected 50 items + + test_50.py FF + + =================================== FAILURES =================================== + _________________________________ test_num[17] _________________________________ + + i = 17 + + @pytest.mark.parametrize("i", range(50)) + def test_num(i): + if i in (17,25): + > pytest.fail("bad luck") + E Failed: bad luck + + test_50.py:6: Failed + _________________________________ test_num[25] _________________________________ + + i = 25 + + @pytest.mark.parametrize("i", range(50)) + def test_num(i): + if i in (17,25): + > pytest.fail("bad luck") + E Failed: bad luck + + test_50.py:6: Failed + =================== 2 failed, 48 deselected in 0.02 seconds ==================== + +The last line indicates that 48 tests have not been run. + +If you run with the ``--ff`` option, all tests will be run but the first +failures will be executed first (as can be seen from the series of ``FF`` and +dots):: + + $ py.test --ff + ============================= test session starts ============================== + platform linux2 -- Python 2.7.3 -- pytest-2.3.5 + run-last-failure: rerun last 2 failures first + plugins: cache + collected 50 items + + test_50.py FF................................................ + + =================================== FAILURES =================================== + _________________________________ test_num[17] _________________________________ + + i = 17 + + @pytest.mark.parametrize("i", range(50)) + def test_num(i): + if i in (17,25): + > pytest.fail("bad luck") + E Failed: bad luck + + test_50.py:6: Failed + _________________________________ test_num[25] _________________________________ + + i = 25 + + @pytest.mark.parametrize("i", range(50)) + def test_num(i): + if i in (17,25): + > pytest.fail("bad luck") + E Failed: bad luck + + test_50.py:6: Failed + ===================== 2 failed, 48 passed in 0.07 seconds ====================== + +.. _`config.cache`: + +The new config.cache object +-------------------------------- + +.. regendoc:wipe + +Plugins or conftest.py support code can get a cached value +using the pytest ``config`` object. Here is a basic example +plugin which implements a `funcarg `_ +which re-uses previously created state across py.test invocations:: + + # content of test_caching.py + import time + + def pytest_funcarg__mydata(request): + val = request.config.cache.get("example/value", None) + if val is None: + time.sleep(9*0.6) # expensive computation :) + val = 42 + request.config.cache.set("example/value", val) + return val + + def test_function(mydata): + assert mydata == 23 + +If you run this command once, it will take a while because +of the sleep:: + + $ py.test -q + F + =================================== FAILURES =================================== + ________________________________ test_function _________________________________ + + mydata = 42 + + def test_function(mydata): + > assert mydata == 23 + E assert 42 == 23 + + test_caching.py:12: AssertionError + +If you run it a second time the value will be retrieved from +the cache and this will be quick:: + + $ py.test -q + F + =================================== FAILURES =================================== + ________________________________ test_function _________________________________ + + mydata = 42 + + def test_function(mydata): + > assert mydata == 23 + E assert 42 == 23 + + test_caching.py:12: AssertionError + +Consult the `pytest-cache API `_ +for more details. + + +Inspecting Cache content +------------------------------- + +You can always peek at the content of the cache using the +``--cache`` command line option:: + + $ py.test --cache + ============================= test session starts ============================== + platform linux2 -- Python 2.7.3 -- pytest-2.3.5 + plugins: cache + cachedir: /tmp/doc-exec-6/.cache + --------------------------------- cache values --------------------------------- + example/value contains: + 42 + cache/lastfailed contains: + set(['test_caching.py::test_function']) + + =============================== in 0.01 seconds =============================== + +Clearing Cache content +------------------------------- + +You can instruct pytest to clear all cache files and values +by adding the ``--clearcache`` option like this:: + + py.test --clearcache + +This is recommended for invocations from Continous Integration +servers where isolation and correctness is more important +than speed. + +Notes +------------- + +repository: http://bitbucket.org/hpk42/pytest-cache + +Issues: repository: http://bitbucket.org/hpk42/pytest-cache/issues + +more info on py.test: http://pytest.org + + +config.cache API +======================================== + +The ``cache`` plugin adds a ``config.cache`` +object during the configure-initialization of pytest. +This allows other plugins, including ``conftest.py`` files, +to safely and flexibly store and retrieve values across +test runs because the ``config`` object is available +in many places. + +Under the hood, the cache plugin uses the simple +`dumps/loads`_ API of the cross-interpreter +execnet_ communication library. It makes it safe +to store values e. g. under Python2 and retrieve +it later from a Python3 or PyPy interpreter. + +.. _`dumps/loads`: http://codespeak.net/execnet/basics.html#dumps-loads +.. _`execnet`: http://codespeak.net/execnet/ + +.. currentmodule:: pytest_cache + +.. automethod:: Cache.get +.. automethod:: Cache.set +.. automethod:: Cache.makedir + Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Fri Feb 27 17:40:56 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 16:40:56 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 397 Message-ID: <20150227164049.53155.82562@drone.io> Build Failed Build : https://drone.io/bitbucket.org/hpk42/pytest/397 Project : https://drone.io/bitbucket.org/hpk42/pytest Repository : https://bitbucket.org/hpk42/pytest Version : Author : Branch : merge-cache Message: -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:03:25 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:03:25 +0000 Subject: [Pytest-commit] [SUCCESS] pytest-xdist - # 1 Message-ID: <20150227170322.39576.86310@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest-xdist/1 Project : https://drone.io/bitbucket.org/pytest-dev/pytest-xdist Repository : https://bitbucket.org/pytest-dev/pytest-xdist Version : 202:9fdea83d0b99 Author : holger krekel Branch : default Message: fix link to pytest-xdist repository -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:04:29 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:04:29 +0000 Subject: [Pytest-commit] [SUCCESS] py - # 1 Message-ID: <20150227170403.16402.2562@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/py/1 Project : https://drone.io/bitbucket.org/pytest-dev/py Repository : https://bitbucket.org/pytest-dev/py Version : 2270:b8362abe49f1 Author : Bertrand Mathieu Branch : default Message: terminalwriter: fix width when under emacs terminal -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:04:31 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:04:31 +0000 Subject: [Pytest-commit] [SUCCESS] pytest-xprocess - # 1 Message-ID: <20150227170419.39506.60253@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest-xprocess/1 Project : https://drone.io/bitbucket.org/pytest-dev/pytest-xprocess Repository : https://bitbucket.org/pytest-dev/pytest-xprocess Version : 12:38f8f0f493f4 Author : Carl Meyer Branch : default Message: Add ability to specify subprocess environment. -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:04:51 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:04:51 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 3 Message-ID: <20150227170441.20303.50866@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest/3 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4023:aa0dc8752409 Author : Ronny Pfannschmidt Branch : default Message: take in a unpolished copy of the base cache documentation -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:06:43 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:06:43 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 4 Message-ID: <20150227170618.20311.45579@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest/4 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4023:aa0dc8752409 Author : Ronny Pfannschmidt Branch : default Message: take in a unpolished copy of the base cache documentation -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:07:11 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:07:11 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 5 Message-ID: <20150227170641.77548.92651@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest/5 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4023:aa0dc8752409 Author : Ronny Pfannschmidt Branch : default Message: take in a unpolished copy of the base cache documentation -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:20:44 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:20:44 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 6 Message-ID: <20150227172002.53165.87581@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest/6 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4023:aa0dc8752409 Author : Ronny Pfannschmidt Branch : default Message: take in a unpolished copy of the base cache documentation -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:20:44 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:20:44 +0000 Subject: [Pytest-commit] [FAIL] pytest-xprocess - # 2 Message-ID: <20150227172028.53159.82195@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest-xprocess/2 Project : https://drone.io/bitbucket.org/pytest-dev/pytest-xprocess Repository : https://bitbucket.org/pytest-dev/pytest-xprocess Version : 12:38f8f0f493f4 Author : Carl Meyer Branch : default Message: Add ability to specify subprocess environment. -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:21:19 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:21:19 +0000 Subject: [Pytest-commit] [FAIL] py - # 2 Message-ID: <20150227172119.10066.46027@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/py/2 Project : https://drone.io/bitbucket.org/pytest-dev/py Repository : https://bitbucket.org/pytest-dev/py Version : 2270:b8362abe49f1 Author : Bertrand Mathieu Branch : default Message: terminalwriter: fix width when under emacs terminal -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:23:27 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:23:27 +0000 Subject: [Pytest-commit] [FAIL] pytest-xdist - # 2 Message-ID: <20150227172326.19144.85074@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest-xdist/2 Project : https://drone.io/bitbucket.org/pytest-dev/pytest-xdist Repository : https://bitbucket.org/pytest-dev/pytest-xdist Version : 202:9fdea83d0b99 Author : holger krekel Branch : default Message: fix link to pytest-xdist repository -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:35:41 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:35:41 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 7 Message-ID: <20150227173540.19164.7426@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest/7 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4023:aa0dc8752409 Author : Ronny Pfannschmidt Branch : default Message: take in a unpolished copy of the base cache documentation -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:48:25 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:48:25 +0000 Subject: [Pytest-commit] [FAIL] pytest - # 8 Message-ID: <20150227174825.15304.27399@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest/8 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4023:aa0dc8752409 Author : Ronny Pfannschmidt Branch : default Message: take in a unpolished copy of the base cache documentation -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:49:17 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:49:17 +0000 Subject: [Pytest-commit] [SUCCESS] py - # 3 Message-ID: <20150227174916.19160.52254@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/py/3 Project : https://drone.io/bitbucket.org/pytest-dev/py Repository : https://bitbucket.org/pytest-dev/py Version : 2270:b8362abe49f1 Author : Bertrand Mathieu Branch : default Message: terminalwriter: fix width when under emacs terminal -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:49:46 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:49:46 +0000 Subject: [Pytest-commit] [FAIL] pytest-xprocess - # 3 Message-ID: <20150227174944.39391.86849@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest-xprocess/3 Project : https://drone.io/bitbucket.org/pytest-dev/pytest-xprocess Repository : https://bitbucket.org/pytest-dev/pytest-xprocess Version : 12:38f8f0f493f4 Author : Carl Meyer Branch : default Message: Add ability to specify subprocess environment. -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Fri Feb 27 18:52:05 2015 From: builds at drone.io (Drone.io Build) Date: Fri, 27 Feb 2015 17:52:05 +0000 Subject: [Pytest-commit] [FAIL] pytest-xdist - # 3 Message-ID: <20150227175205.34514.76870@drone.io> Build Failed Build : https://drone.io/bitbucket.org/pytest-dev/pytest-xdist/3 Project : https://drone.io/bitbucket.org/pytest-dev/pytest-xdist Repository : https://bitbucket.org/pytest-dev/pytest-xdist Version : 202:9fdea83d0b99 Author : holger krekel Branch : default Message: fix link to pytest-xdist repository -------------- next part -------------- An HTML attachment was scrubbed... URL: From issues-reply at bitbucket.org Fri Feb 27 20:11:43 2015 From: issues-reply at bitbucket.org (Daniel Hahler) Date: Fri, 27 Feb 2015 19:11:43 -0000 Subject: [Pytest-commit] Issue #689: Allow for pytester to not redirect stdio (ipdb.set_trace() etc) (pytest-dev/pytest) Message-ID: <20150227191143.29495.95563@app06.ash-private.bitbucket.org> New issue 689: Allow for pytester to not redirect stdio (ipdb.set_trace() etc) https://bitbucket.org/pytest-dev/pytest/issue/689/allow-for-pytester-to-not-redirect-stdio Daniel Hahler: I would like to use `ipbd.set_trace()` (interactively) from a test, like this: ``` #!python def test_runpytest_ipdb(self, testdir): testdir.makepyfile(""" def test_foo(): import ipdb; ipdb.set_trace() """) result = testdir.runpytest('-s') ``` When running this test (using `py.test -s`), the test will "hang"; nothing gets displayed. You can interact with the debugger, and quit it using `Ctrl-d`. From issues-reply at bitbucket.org Sat Feb 28 00:21:19 2015 From: issues-reply at bitbucket.org (Brianna Laugher) Date: Fri, 27 Feb 2015 23:21:19 -0000 Subject: [Pytest-commit] Issue #690: yield_fixture docs need updating (pytest-dev/pytest) Message-ID: <20150227232119.20898.37429@app07.ash-private.bitbucket.org> New issue 690: yield_fixture docs need updating https://bitbucket.org/pytest-dev/pytest/issue/690/yield_fixture-docs-need-updating Brianna Laugher: http://pytest.org/latest/yieldfixture.html says *?yielding? fixture values is an experimental feature and its exact declaration may change later but earliest in a 2.5 release. You can thus safely use this feature in the 2.4 series but may need to adapt later.* I think it is not actually the case that it is still experimental - it can cause confusion about if this feature should be used or not. I am not sure what exactly the official status of it is now, so perhaps someone else can suggest what the wording should be. From commits-noreply at bitbucket.org Sat Feb 28 10:03:03 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 28 Feb 2015 09:03:03 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: Close branch issue616 Message-ID: <20150228090303.24987.86014@app06.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/525082e4ed8e/ Changeset: 525082e4ed8e Branch: issue616 User: RonnyPfannschmidt Date: 2015-02-28 09:02:58+00:00 Summary: Close branch issue616 Affected #: 0 files Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 28 10:03:03 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 28 Feb 2015 09:03:03 -0000 Subject: [Pytest-commit] commit/pytest: RonnyPfannschmidt: Merged in issue616 (pull request #252) Message-ID: <20150228090303.25183.18795@app02.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/9c7946ebb69c/ Changeset: 9c7946ebb69c User: RonnyPfannschmidt Date: 2015-02-28 09:02:58+00:00 Summary: Merged in issue616 (pull request #252) fix issue616 - conftest visibility fixes. Affected #: 13 files diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,20 @@ 2.7.0.dev (compared to 2.6.4) ----------------------------- +- fix issue616: conftest.py files and their contained fixutres are now + properly considered for visibility, independently from the exact + current working directory and test arguments that are used. + Many thanks to Eric Siegerman and his PR235 which contains + systematic tests for conftest visibility and now passes. + This change also introduces the concept of a ``rootdir`` which + is printed as a new pytest header and documented in the pytest + customize web page. + +- change reporting of "diverted" tests, i.e. tests that are collected + in one file but actually come from another (e.g. when tests in a test class + come from a base class in a different file). We now show the nodeid + and indicate via a postfix the other file. + - add ability to set command line options by environment variable PYTEST_ADDOPTS. - added documentation on the new pytest-dev teams on bitbucket and diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d _pytest/config.py --- a/_pytest/config.py +++ b/_pytest/config.py @@ -657,6 +657,12 @@ sys.stderr.write("INTERNALERROR> %s\n" %line) sys.stderr.flush() + def cwd_relative_nodeid(self, nodeid): + # nodeid's are relative to the rootpath, compute relative to cwd + if self.invocation_dir != self.rootdir: + fullpath = self.rootdir.join(nodeid) + nodeid = self.invocation_dir.bestrelpath(fullpath) + return nodeid @classmethod def fromdictargs(cls, option_dict, args): @@ -691,14 +697,9 @@ def _initini(self, args): parsed_args = self._parser.parse_known_args(args) - if parsed_args.inifilename: - iniconfig = py.iniconfig.IniConfig(parsed_args.inifilename) - if 'pytest' in iniconfig.sections: - self.inicfg = iniconfig['pytest'] - else: - self.inicfg = {} - else: - self.inicfg = getcfg(args, ["pytest.ini", "tox.ini", "setup.cfg"]) + r = determine_setup(parsed_args.inifilename, parsed_args.file_or_dir) + self.rootdir, self.inifile, self.inicfg = r + self.invocation_dir = py.path.local() self._parser.addini('addopts', 'extra command line options', 'args') self._parser.addini('minversion', 'minimally required pytest version') @@ -859,8 +860,58 @@ if exists(p): iniconfig = py.iniconfig.IniConfig(p) if 'pytest' in iniconfig.sections: - return iniconfig['pytest'] - return {} + return base, p, iniconfig['pytest'] + elif inibasename == "pytest.ini": + # allowed to be empty + return base, p, {} + return None, None, None + + +def get_common_ancestor(args): + # args are what we get after early command line parsing (usually + # strings, but can be py.path.local objects as well) + common_ancestor = None + for arg in args: + if str(arg)[0] == "-": + continue + p = py.path.local(arg) + if common_ancestor is None: + common_ancestor = p + else: + if p.relto(common_ancestor) or p == common_ancestor: + continue + elif common_ancestor.relto(p): + common_ancestor = p + else: + shared = p.common(common_ancestor) + if shared is not None: + common_ancestor = shared + if common_ancestor is None: + common_ancestor = py.path.local() + elif not common_ancestor.isdir(): + common_ancestor = common_ancestor.dirpath() + return common_ancestor + + +def determine_setup(inifile, args): + if inifile: + iniconfig = py.iniconfig.IniConfig(inifile) + try: + inicfg = iniconfig["pytest"] + except KeyError: + inicfg = None + rootdir = get_common_ancestor(args) + else: + ancestor = get_common_ancestor(args) + rootdir, inifile, inicfg = getcfg( + [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"]) + if rootdir is None: + for rootdir in ancestor.parts(reverse=True): + if rootdir.join("setup.py").exists(): + break + else: + rootdir = ancestor + return rootdir, inifile, inicfg or {} def setns(obj, dic): diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d _pytest/main.py --- a/_pytest/main.py +++ b/_pytest/main.py @@ -457,9 +457,7 @@ self.fspath = fspath def _makeid(self): - if self == self.session: - return "." - relpath = self.session.fspath.bestrelpath(self.fspath) + relpath = self.fspath.relto(self.config.rootdir) if os.sep != "/": relpath = relpath.replace(os.sep, "/") return relpath @@ -510,7 +508,7 @@ __module__ = 'builtins' # for py3 def __init__(self, config): - FSCollector.__init__(self, py.path.local(), parent=None, + FSCollector.__init__(self, config.rootdir, parent=None, config=config, session=self) self.config.pluginmanager.register(self, name="session", prepend=True) self._testsfailed = 0 @@ -520,6 +518,9 @@ self.startdir = py.path.local() self._fs2hookproxy = {} + def _makeid(self): + return "" + def pytest_collectstart(self): if self.shouldstop: raise self.Interrupted(self.shouldstop) @@ -663,7 +664,7 @@ arg = self._tryconvertpyarg(arg) parts = str(arg).split("::") relpath = parts[0].replace("/", os.sep) - path = self.fspath.join(relpath, abs=True) + path = self.config.invocation_dir.join(relpath, abs=True) if not path.check(): if self.config.option.pyargs: msg = "file or package not found: " diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d _pytest/pytester.py --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -306,9 +306,8 @@ session = Session(config) assert '::' not in str(arg) p = py.path.local(arg) - x = session.fspath.bestrelpath(p) config.hook.pytest_sessionstart(session=session) - res = session.perform_collect([x], genitems=False)[0] + res = session.perform_collect([str(p)], genitems=False)[0] config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) return res @@ -395,8 +394,7 @@ def parseconfigure(self, *args): config = self.parseconfig(*args) config.do_configure() - self.request.addfinalizer(lambda: - config.do_unconfigure()) + self.request.addfinalizer(config.do_unconfigure) return config def getitem(self, source, funcname="test_func"): diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1653,11 +1653,9 @@ # what fixtures are visible for particular tests (as denoted # by their test id) if p.basename.startswith("conftest.py"): - nodeid = self.session.fspath.bestrelpath(p.dirpath()) + nodeid = p.dirpath().relto(self.config.rootdir) if p.sep != "/": nodeid = nodeid.replace(p.sep, "/") - if nodeid == ".": - nodeid = "" self.parsefactories(plugin, nodeid) self._seenplugins.add(plugin) diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d _pytest/skipping.py --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -218,14 +218,14 @@ failed = terminalreporter.stats.get(stat) if failed: for rep in failed: - pos = rep.nodeid - lines.append(format %(pos, )) + pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid) + lines.append(format %(pos,)) def show_xfailed(terminalreporter, lines): xfailed = terminalreporter.stats.get("xfailed") if xfailed: for rep in xfailed: - pos = rep.nodeid + pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid) reason = rep.wasxfail lines.append("XFAIL %s" % (pos,)) if reason: @@ -235,7 +235,7 @@ xpassed = terminalreporter.stats.get("xpassed") if xpassed: for rep in xpassed: - pos = rep.nodeid + pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid) reason = rep.wasxfail lines.append("XPASS %s %s" %(pos, reason)) diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d _pytest/terminal.py --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -95,7 +95,7 @@ self._numcollected = 0 self.stats = {} - self.startdir = self.curdir = py.path.local() + self.startdir = py.path.local() if file is None: file = sys.stdout self._tw = self.writer = py.io.TerminalWriter(file) @@ -111,12 +111,12 @@ char = {'xfailed': 'x', 'skipped': 's'}.get(char, char) return char in self.reportchars - def write_fspath_result(self, fspath, res): + def write_fspath_result(self, nodeid, res): + fspath = self.config.rootdir.join(nodeid.split("::")[0]) if fspath != self.currentfspath: self.currentfspath = fspath - #fspath = self.startdir.bestrelpath(fspath) + fspath = self.startdir.bestrelpath(fspath) self._tw.line() - #relpath = self.startdir.bestrelpath(fspath) self._tw.write(fspath + " ") self._tw.write(res) @@ -182,12 +182,12 @@ def pytest_runtest_logstart(self, nodeid, location): # ensure that the path is printed before the # 1st test of a module starts running - fspath = nodeid.split("::")[0] if self.showlongtestinfo: - line = self._locationline(fspath, *location) + line = self._locationline(nodeid, *location) self.write_ensure_prefix(line, "") elif self.showfspath: - self.write_fspath_result(fspath, "") + fsid = nodeid.split("::")[0] + self.write_fspath_result(fsid, "") def pytest_runtest_logreport(self, report): rep = report @@ -200,7 +200,7 @@ return if self.verbosity <= 0: if not hasattr(rep, 'node') and self.showfspath: - self.write_fspath_result(rep.fspath, letter) + self.write_fspath_result(rep.nodeid, letter) else: self._tw.write(letter) else: @@ -213,7 +213,7 @@ markup = {'red':True} elif rep.skipped: markup = {'yellow':True} - line = self._locationline(str(rep.fspath), *rep.location) + line = self._locationline(rep.nodeid, *rep.location) if not hasattr(rep, 'node'): self.write_ensure_prefix(line, word, **markup) #self._tw.write(word, **markup) @@ -237,7 +237,7 @@ items = [x for x in report.result if isinstance(x, pytest.Item)] self._numcollected += len(items) if self.hasmarkup: - #self.write_fspath_result(report.fspath, 'E') + #self.write_fspath_result(report.nodeid, 'E') self.report_collect() def report_collect(self, final=False): @@ -288,6 +288,10 @@ self.write_line(line) def pytest_report_header(self, config): + inifile = "" + if config.inifile: + inifile = config.rootdir.bestrelpath(config.inifile) + lines = ["rootdir: %s, inifile: %s" %(config.rootdir, inifile)] plugininfo = config.pluginmanager._plugin_distinfo if plugininfo: l = [] @@ -296,7 +300,8 @@ if name.startswith("pytest-"): name = name[7:] l.append(name) - return "plugins: %s" % ", ".join(l) + lines.append("plugins: %s" % ", ".join(l)) + return lines def pytest_collection_finish(self, session): if self.config.option.collectonly: @@ -378,19 +383,24 @@ else: excrepr.reprcrash.toterminal(self._tw) - def _locationline(self, collect_fspath, fspath, lineno, domain): + def _locationline(self, nodeid, fspath, lineno, domain): + def mkrel(nodeid): + line = self.config.cwd_relative_nodeid(nodeid) + if domain and line.endswith(domain): + line = line[:-len(domain)] + l = domain.split("[") + l[0] = l[0].replace('.', '::') # don't replace '.' in params + line += "[".join(l) + return line # collect_fspath comes from testid which has a "/"-normalized path - if fspath and fspath.replace("\\", "/") != collect_fspath: - fspath = "%s <- %s" % (collect_fspath, fspath) + if fspath: - line = str(fspath) - if domain: - split = str(domain).split('[') - split[0] = split[0].replace('.', '::') # don't replace '.' in params - line += "::" + '['.join(split) + res = mkrel(nodeid).replace("::()", "") # parens-normalization + if nodeid.split("::")[0] != fspath.replace("\\", "/"): + res += " <- " + self.startdir.bestrelpath(fspath) else: - line = "[location]" - return line + " " + res = "[location]" + return res + " " def _getfailureheadline(self, rep): if hasattr(rep, 'location'): diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d doc/en/customize.txt --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -12,37 +12,73 @@ This will display command line and configuration file settings which were registered by installed plugins. +.. _rootdir: .. _inifiles: -How test configuration is read from configuration INI-files -------------------------------------------------------------- +initialization: determining rootdir and inifile +----------------------------------------------- -``pytest`` searches for the first matching ini-style configuration file -in the directories of command line argument and the directories above. -It looks for file basenames in this order:: +.. versionadded:: 2.7 +pytest determines a "rootdir" for each test run which depends on +the command line arguments (specified test files, paths) and on +the existence of inifiles. The determined rootdir and ini-file are +printed as part of the pytest header. The rootdir is used for constructing +"nodeids" during collection and may also be used by plugins to store +project/testrun-specific information. + +Here is the algorithm which finds the rootdir from ``args``: + +- determine the common ancestor directory for the specified ``args``. + +- look for ``pytest.ini``, ``tox.ini`` and ``setup.cfg`` files in the + ancestor directory and upwards. If one is matched, it becomes the + ini-file and its directory becomes the rootdir. An existing + ``pytest.ini`` file will always be considered a match whereas + ``tox.ini`` and ``setup.cfg`` will only match if they contain + a ``[pytest]`` section. + +- if no ini-file was found, look for ``setup.py`` upwards from + the common ancestor directory to determine the ``rootdir``. + +- if no ini-file and no ``setup.py`` was found, use the already + determined common ancestor as root directory. This allows to + work with pytest in structures that are not part of a package + and don't have any particular ini-file configuration. + +Note that options from multiple ini-files candidates are never merged, +the first one wins (``pytest.ini`` always wins even if it does not +contain a ``[pytest]`` section). + +The ``config`` object will subsequently carry these attributes: + +- ``config.rootdir``: the determined root directory, guaranteed to exist. + +- ``config.inifile``: the determined ini-file, may be ``None``. + +The rootdir is used a reference directory for constructing test +addresses ("nodeids") and can be used also by plugins for storing +per-testrun information. + +Example:: + + py.test path/to/testdir path/other/ + +will determine the common ancestor as ``path`` and then +check for ini-files as follows:: + + # first look for pytest.ini files + path/pytest.ini + path/setup.cfg # must also contain [pytest] section to match + path/tox.ini # must also contain [pytest] section to match pytest.ini - tox.ini - setup.cfg + ... # all the way down to the root -Searching stops when the first ``[pytest]`` section is found in any of -these files. There is no merging of configuration values from multiple -files. Example:: + # now look for setup.py + path/setup.py + setup.py + ... # all the way down to the root - py.test path/to/testdir - -will look in the following dirs for a config file:: - - path/to/testdir/pytest.ini - path/to/testdir/tox.ini - path/to/testdir/setup.cfg - path/to/pytest.ini - path/to/tox.ini - path/to/setup.cfg - ... # up until root of filesystem - -If argument is provided to a ``pytest`` run, the current working directory -is used to start the search. .. _`how to change command line options defaults`: .. _`adding default options`: @@ -67,6 +103,8 @@ From now on, running ``pytest`` will add the specified options. + + Builtin configuration file options ---------------------------------------------- diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d testing/test_collection.py --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -343,7 +343,7 @@ ("pytest_make_collect_report", "collector.fspath == p"), ("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_collectreport", "report.nodeid.startswith(p.basename)"), - ("pytest_collectreport", "report.nodeid == '.'") + ("pytest_collectreport", "report.nodeid == ''") ]) def test_collect_protocol_method(self, testdir): @@ -478,7 +478,7 @@ config = testdir.parseconfigure(x) col = testdir.getnode(config, x) assert isinstance(col, pytest.Module) - assert col.name == 'subdir/x.py' + assert col.name == 'x.py' assert col.parent.parent is None for col in col.listchain(): assert col.config is config diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d testing/test_config.py --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,6 +1,6 @@ import py, pytest -from _pytest.config import getcfg +from _pytest.config import getcfg, get_common_ancestor, determine_setup class TestParseIni: def test_getcfg_and_config(self, testdir, tmpdir): @@ -10,7 +10,7 @@ [pytest] name = value """)) - cfg = getcfg([sub], ["setup.cfg"]) + rootdir, inifile, cfg = getcfg([sub], ["setup.cfg"]) assert cfg['name'] == "value" config = testdir.parseconfigure(sub) assert config.inicfg['name'] == 'value' @@ -400,3 +400,55 @@ *WT1*test_warn_on_test_item*:5*hello* *1 warning* """) + +class TestRootdir: + def test_simple_noini(self, tmpdir): + assert get_common_ancestor([tmpdir]) == tmpdir + assert get_common_ancestor([tmpdir.mkdir("a"), tmpdir]) == tmpdir + assert get_common_ancestor([tmpdir, tmpdir.join("a")]) == tmpdir + with tmpdir.as_cwd(): + assert get_common_ancestor([]) == tmpdir + + @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split()) + def test_with_ini(self, tmpdir, name): + inifile = tmpdir.join(name) + inifile.write("[pytest]\n") + + a = tmpdir.mkdir("a") + b = a.mkdir("b") + for args in ([tmpdir], [a], [b]): + rootdir, inifile, inicfg = determine_setup(None, args) + assert rootdir == tmpdir + assert inifile == inifile + rootdir, inifile, inicfg = determine_setup(None, [b,a]) + assert rootdir == tmpdir + assert inifile == inifile + + @pytest.mark.parametrize("name", "setup.cfg tox.ini".split()) + def test_pytestini_overides_empty_other(self, tmpdir, name): + inifile = tmpdir.ensure("pytest.ini") + a = tmpdir.mkdir("a") + a.ensure(name) + rootdir, inifile, inicfg = determine_setup(None, [a]) + assert rootdir == tmpdir + assert inifile == inifile + + def test_setuppy_fallback(self, tmpdir): + a = tmpdir.mkdir("a") + a.ensure("setup.cfg") + tmpdir.ensure("setup.py") + rootdir, inifile, inicfg = determine_setup(None, [a]) + assert rootdir == tmpdir + assert inifile is None + assert inicfg == {} + + def test_nothing(self, tmpdir): + rootdir, inifile, inicfg = determine_setup(None, [tmpdir]) + assert rootdir == tmpdir + assert inifile is None + assert inicfg == {} + + def test_with_specific_inifile(self, tmpdir): + inifile = tmpdir.ensure("pytest.ini") + rootdir, inifile, inicfg = determine_setup(inifile, [tmpdir]) + assert rootdir == tmpdir diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d testing/test_conftest.py --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,7 +1,9 @@ +from textwrap import dedent import py, pytest from _pytest.config import Conftest + @pytest.fixture(scope="module", params=["global", "inpackage"]) def basedir(request): from _pytest.tmpdir import tmpdir @@ -255,3 +257,89 @@ result.stdout.fnmatch_lines(""" *--hello-world* """) + + +class TestConftestVisibility: + def _setup_tree(self, testdir): # for issue616 + # example mostly taken from: + # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html + runner = testdir.mkdir("empty") + package = testdir.mkdir("package") + + package.join("conftest.py").write(dedent("""\ + import pytest + @pytest.fixture + def fxtr(): + return "from-package" + """)) + package.join("test_pkgroot.py").write(dedent("""\ + def test_pkgroot(fxtr): + assert fxtr == "from-package" + """)) + + swc = package.mkdir("swc") + swc.join("__init__.py").ensure() + swc.join("conftest.py").write(dedent("""\ + import pytest + @pytest.fixture + def fxtr(): + return "from-swc" + """)) + swc.join("test_with_conftest.py").write(dedent("""\ + def test_with_conftest(fxtr): + assert fxtr == "from-swc" + + """)) + + snc = package.mkdir("snc") + snc.join("__init__.py").ensure() + snc.join("test_no_conftest.py").write(dedent("""\ + def test_no_conftest(fxtr): + assert fxtr == "from-package" # No local conftest.py, so should + # use value from parent dir's + + """)) + print ("created directory structure:") + for x in testdir.tmpdir.visit(): + print (" " + x.relto(testdir.tmpdir)) + + return { + "runner": runner, + "package": package, + "swc": swc, + "snc": snc} + + # 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", [ + ("runner", "..", 3), + ("package", "..", 3), + ("swc", "../..", 3), + ("snc", "../..", 3), + + ("runner", "../package", 3), + ("package", ".", 3), + ("swc", "..", 3), + ("snc", "..", 3), + + ("runner", "../package/swc", 1), + ("package", "./swc", 1), + ("swc", ".", 1), + ("snc", "../swc", 1), + + ("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): + dirs = self._setup_tree(testdir) + print("pytest run in cwd: %s" %( + dirs[chdir].relto(testdir.tmpdir))) + 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) diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d testing/test_doctest.py --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,9 +1,6 @@ from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile import py, pytest -import pdb - - class TestDoctests: def test_collect_testtextfile(self, testdir): diff -r f7f076b07d105d2fceeb38c998910be33f9fe290 -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d testing/test_terminal.py --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -77,11 +77,11 @@ def test_writeline(self, testdir, linecomp): modcol = testdir.getmodulecol("def test_one(): pass") rep = TerminalReporter(modcol.config, file=linecomp.stringio) - rep.write_fspath_result(py.path.local("xy.py"), '.') + rep.write_fspath_result(modcol.nodeid, ".") rep.write_line("hello world") lines = linecomp.stringio.getvalue().split('\n') assert not lines[0] - assert lines[1].endswith("xy.py .") + assert lines[1].endswith(modcol.name + " .") assert lines[2] == "hello world" def test_show_runtest_logstart(self, testdir, linecomp): @@ -126,7 +126,7 @@ ]) result = testdir.runpytest("-v", p2) result.stdout.fnmatch_lines([ - "*test_p2.py <- *test_p1.py::TestMore::test_p1*", + "*test_p2.py::TestMore::test_p1* <- *test_p1.py*PASSED", ]) def test_itemreport_directclasses_not_shown_as_subclasses(self, testdir): Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sat Feb 28 10:16:48 2015 From: builds at drone.io (Drone.io Build) Date: Sat, 28 Feb 2015 09:16:48 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 9 Message-ID: <20150228091648.34514.73644@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest/9 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 3868:525082e4ed8e Author : Ronny Pfannschmidt Branch : issue616 Message: Close branch issue616 -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Sat Feb 28 10:29:28 2015 From: builds at drone.io (Drone.io Build) Date: Sat, 28 Feb 2015 09:29:28 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 10 Message-ID: <20150228092928.77534.88072@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest/10 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4025:9c7946ebb69c Author : Ronny Pfannschmidt Branch : default Message: Merged in issue616 (pull request #252) -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sat Feb 28 20:02:52 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 28 Feb 2015 19:02:52 -0000 Subject: [Pytest-commit] commit/pytest: hpk42: mention "pytestdotorg" twitter account Message-ID: <20150228190252.27672.88711@app02.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/c3dd3f237dd4/ Changeset: c3dd3f237dd4 User: hpk42 Date: 2015-02-28 19:02:31+00:00 Summary: mention "pytestdotorg" twitter account Affected #: 1 file diff -r 9c7946ebb69c7d4c778e5e6c46e026ca715ae18d -r c3dd3f237dd4cf8cbfa61ce1522f979f77d6e7b7 doc/en/adopt.txt --- a/doc/en/adopt.txt +++ b/doc/en/adopt.txt @@ -6,7 +6,7 @@ We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest. -In 2015 we are trying this for the first time. In February and March 2015 we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `issue tracker`_ or the `pytest-dev mailing list`_. +In 2015 we are trying this for the first time. In February and March 2015 we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `@pytestdotorg twitter account `_ the `issue tracker`_ or the `pytest-dev mailing list`_. .. _`issue tracker`: https://bitbucket.org/pytest-dev/pytest/issue/676/adopt-pytest-month-2015 Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sat Feb 28 20:15:50 2015 From: builds at drone.io (Drone.io Build) Date: Sat, 28 Feb 2015 19:15:50 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 11 Message-ID: <20150228191550.77550.37221@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest/11 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4026:c3dd3f237dd4 Author : holger krekel Branch : default Message: mention "pytestdotorg" twitter account -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sat Feb 28 21:33:00 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 28 Feb 2015 20:33:00 -0000 Subject: [Pytest-commit] commit/pytest: bubenkoff: Close branch plugincompat-move Message-ID: <20150228203300.20489.78983@app12.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/ebe73a63994f/ Changeset: ebe73a63994f Branch: plugincompat-move User: bubenkoff Date: 2015-02-28 20:32:57+00:00 Summary: Close branch plugincompat-move Affected #: 0 files Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sat Feb 28 21:36:48 2015 From: builds at drone.io (Drone.io Build) Date: Sat, 28 Feb 2015 20:36:48 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 12 Message-ID: <20150228203648.16400.15767@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest/12 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 3891:5294eee465a2 Author : Bruno Oliveira Branch : plugincompat-move Message: moved pytest-plugs to plugincompat -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits-noreply at bitbucket.org Sat Feb 28 21:23:42 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 28 Feb 2015 20:23:42 -0000 Subject: [Pytest-commit] commit/pytest: nicoddemus: moved pytest-plugs to plugincompat Message-ID: <20150228202342.14811.14777@app10.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/5294eee465a2/ Changeset: 5294eee465a2 Branch: plugincompat-move User: nicoddemus Date: 2015-02-28 20:22:42+00:00 Summary: moved pytest-plugs to plugincompat also plugins_index is ready for 2.7.0 release Affected #: 3 files diff -r c3dd3f237dd4cf8cbfa61ce1522f979f77d6e7b7 -r 5294eee465a2b5c072b1e191d2cb2540a7c9d962 doc/en/plugins.txt --- a/doc/en/plugins.txt +++ b/doc/en/plugins.txt @@ -112,7 +112,7 @@ To see a complete list of all plugins with their latest testing status against different py.test and Python versions, please visit -`pytest-plugs `_. +`plugincompat `_. You may also discover more plugins through a `pytest- pypi.python.org search`_. diff -r c3dd3f237dd4cf8cbfa61ce1522f979f77d6e7b7 -r 5294eee465a2b5c072b1e191d2cb2540a7c9d962 doc/en/plugins_index/index.txt --- a/doc/en/plugins_index/index.txt +++ b/doc/en/plugins_index/index.txt @@ -4,168 +4,224 @@ =========================== The table below contains a listing of plugins found in PyPI and -their status when tested using py.test **2.6.4.dev1** and python 2.7 and +their status when tested using py.test **2.7.0** and python 2.7 and 3.3. A complete listing can also be found at -`pytest-plugs `_, which contains tests +`plugincompat `_, which contains tests status against other py.test releases. -==================================================================================== ================================================================================================================= ================================================================================================================= =========================================================================== ============================================================================================================================================= - Name Py27 Py34 Home Summary -==================================================================================== ================================================================================================================= ================================================================================================================= =========================================================================== ============================================================================================================================================= - `pytest-allure-adaptor `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-allure-adaptor-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-allure-adaptor-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Plugin for py.test to generate allure xml reports - :target: http://pytest-plugs.herokuapp.com/output/pytest-allure-adaptor-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-allure-adaptor-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/allure-framework/allure-python - `pytest-bdd `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png BDD for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/olegpidsadnyi/pytest-bdd - `pytest-beds `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-beds-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-beds-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Fixtures for testing Google Appengine (GAE) apps - :target: http://pytest-plugs.herokuapp.com/output/pytest-beds-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-beds-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/kaste/pytest-beds - `pytest-bench `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Benchmark utility that plugs into pytest. - :target: http://pytest-plugs.herokuapp.com/output/pytest-bench-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bench-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/concordusapps/pytest-bench - `pytest-blockage `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Disable network requests during a test run. - :target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/rob-b/pytest-blockage - `pytest-browsermob-proxy `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png BrowserMob proxy plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/davehunt/pytest-browsermob-proxy - `pytest-bugzilla `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test bugzilla integration plugin - :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nibrahim/pytest_bugzilla - `pytest-cache `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-cache/ - `pytest-capturelog `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to capture log messages - :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/memedough/pytest-capturelog/overview - `pytest-codecheckers `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends) - :target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-codecheckers/ - `pytest-config `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-config-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-config-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Base configurations and utilities for developing your Python project test suite with pytest. - :target: http://pytest-plugs.herokuapp.com/output/pytest-config-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-config-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/buzzfeed/pytest_config - `pytest-contextfixture `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Define pytest fixtures as context managers. - :target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/pelme/pytest-contextfixture/ - `pytest-couchdbkit `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test extension for per-test couchdb databases using couchdbkit - :target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-couchdbkit - `pytest-cov `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing - :target: http://pytest-plugs.herokuapp.com/output/pytest-cov-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cov-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/schlamar/pytest-cov - `pytest-cpp `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cpp-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cpp-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Use pytest's runner to discover and execute C++ tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-cpp-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cpp-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nicoddemus/pytest-cpp - `pytest-dbfixtures `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Databases fixtures plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/ClearcodeHQ/pytest-dbfixtures - `pytest-dbus-notification `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbus-notification-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbus-notification-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png D-BUS notifications for pytest results. - :target: http://pytest-plugs.herokuapp.com/output/pytest-dbus-notification-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-dbus-notification-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bmathieu33/pytest-dbus-notification - `pytest-describe `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-describe-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-describe-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Describe-style plugin for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-describe-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-describe-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/ropez/pytest-describe - `pytest-diffeo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-diffeo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-diffeo-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Common py.test support for Diffeo packages - :target: http://pytest-plugs.herokuapp.com/output/pytest-diffeo-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-diffeo-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/diffeo/pytest-diffeo - `pytest-django `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-latest?py=py34&pytest=2.6.4.dev1 `link `_ A Django plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-django-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-latest?py=py34&pytest=2.6.4.dev1 - `pytest-django-haystack `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-haystack-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-haystack-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Cleanup your Haystack indexes between tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-django-haystack-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-haystack-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/rouge8/pytest-django-haystack - `pytest-django-lite `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png The bare minimum to integrate py.test with Django. - :target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/dcramer/pytest-django-lite - `pytest-echo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-echo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-echo-latest?py=py34&pytest=2.6.4.dev1 `link `_ pytest plugin with mechanisms for echoing environment variables, package version and generic attributes - :target: http://pytest-plugs.herokuapp.com/output/pytest-echo-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-echo-latest?py=py34&pytest=2.6.4.dev1 - `pytest-eradicate `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check for commented out code - :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/spil-johan/pytest-eradicate - `pytest-figleaf `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test figleaf coverage plugin - :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-figleaf - `pytest-fixture-tools `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 ? Plugin for pytest which provides tools for fixtures - :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 - `pytest-flakes `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check source code with pyflakes - :target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/fschulze/pytest-flakes - `pytest-flask `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flask-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flask-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A set of py.test fixtures to test Flask applications. - :target: http://pytest-plugs.herokuapp.com/output/pytest-flask-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-flask-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/vitalk/pytest-flask - `pytest-greendots `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-latest?py=py34&pytest=2.6.4.dev1 ? Green progress dots - :target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-latest?py=py34&pytest=2.6.4.dev1 - `pytest-growl `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-latest?py=py34&pytest=2.6.4.dev1 ? Growl notifications for pytest results. - :target: http://pytest-plugs.herokuapp.com/output/pytest-growl-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-growl-latest?py=py34&pytest=2.6.4.dev1 - `pytest-httpbin `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpbin-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpbin-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Easily test your HTTP library against a local copy of httpbin - :target: http://pytest-plugs.herokuapp.com/output/pytest-httpbin-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-httpbin-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/kevin1024/pytest-httpbin - `pytest-httpretty `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpretty-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpretty-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A thin wrapper of HTTPretty for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-httpretty-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-httpretty-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/papaeye/pytest-httpretty - `pytest-incremental `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png an incremental test runner (pytest plugin) - :target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-latest?py=py34&pytest=2.6.4.dev1 :target: https://bitbucket.org/schettino72/pytest-incremental - `pytest-instafail `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to show failures instantly - :target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/jpvanhal/pytest-instafail - `pytest-ipdb `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A py.test plug-in to enable drop to ipdb debugger on test failure. - :target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/mverteuil/pytest-ipdb - `pytest-jira `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test JIRA integration plugin, using markers - :target: http://pytest-plugs.herokuapp.com/output/pytest-jira-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-jira-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/jlaska/pytest_jira - `pytest-knows `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-knows-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-knows-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A pytest plugin that can automaticly skip test case based on dependence info calculated by trace - :target: http://pytest-plugs.herokuapp.com/output/pytest-knows-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-knows-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/mapix/ptknows - `pytest-konira `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Run Konira DSL tests with py.test - :target: http://pytest-plugs.herokuapp.com/output/pytest-konira-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-konira-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/alfredodeza/pytest-konira - `pytest-localserver `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to test server connections locally. - :target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/basti/pytest-localserver/ - `pytest-marker-bugzilla `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test bugzilla integration plugin, using markers - :target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/eanxgeek/pytest_marker_bugzilla - `pytest-markfiltration `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png UNKNOWN - :target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/adamgoucher/pytest-markfiltration - `pytest-marks `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png UNKNOWN - :target: http://pytest-plugs.herokuapp.com/output/pytest-marks-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marks-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/adamgoucher/pytest-marks - `pytest-mock `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mock-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mock-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Thin-wrapper around the mock package for easier use with py.test - :target: http://pytest-plugs.herokuapp.com/output/pytest-mock-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-mock-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/nicoddemus/pytest-mock/ - `pytest-monkeyplus `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest's monkeypatch subclass with extra functionalities - :target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hsoft/pytest-monkeyplus/ - `pytest-mozwebqa `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Mozilla WebQA plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/davehunt/pytest-mozwebqa - `pytest-oerp `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to test OpenERP modules - :target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/santagada/pytest-oerp/ - `pytest-ordering `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ordering-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ordering-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to run your tests in a specific order - :target: http://pytest-plugs.herokuapp.com/output/pytest-ordering-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-ordering-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/ftobia/pytest-ordering - `pytest-osxnotify `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png OS X notifications for py.test results. - :target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/dbader/pytest-osxnotify - `pytest-paste-config `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 ? Allow setting the path to a paste config file - :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 - `pytest-pep8 `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to check PEP8 requirements - :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-pep8/ - `pytest-pipeline `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines - :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bow/pytest_pipeline - `pytest-poo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Visualize your crappy tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-poo-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-poo-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/pelme/pytest-poo - `pytest-pycharm `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pycharm-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pycharm-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Plugin for py.test to enter PyCharm debugger on uncaught exceptions - :target: http://pytest-plugs.herokuapp.com/output/pytest-pycharm-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pycharm-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/jlubcke/pytest-pycharm - `pytest-pydev `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to connect to a remote debug server with PyDev or PyCharm. - :target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/basti/pytest-pydev/ - `pytest-pythonpath `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pythonpath-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pythonpath-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin for adding to the PYTHONPATH from command line or configs. - :target: http://pytest-plugs.herokuapp.com/output/pytest-pythonpath-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pythonpath-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bigsassy/pytest-pythonpath - `pytest-qt `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest support for PyQt and PySide applications - :target: http://pytest-plugs.herokuapp.com/output/pytest-qt-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-qt-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nicoddemus/pytest-qt - `pytest-quickcheck `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to generate random data inspired by QuickCheck - :target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/t2y/pytest-quickcheck/ - `pytest-rage `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to implement PEP712 - :target: http://pytest-plugs.herokuapp.com/output/pytest-rage-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rage-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/santagada/pytest-rage/ - `pytest-raisesregexp `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-raisesregexp-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-raisesregexp-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Simple pytest plugin to look for regex in Exceptions - :target: http://pytest-plugs.herokuapp.com/output/pytest-raisesregexp-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-raisesregexp-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/Walkman/pytest_raisesregexp - `pytest-random `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to randomize tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-random-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-random-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/klrmn/pytest-random - `pytest-regtest `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-regtest-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-regtest-latest?py=py34&pytest=2.6.4.dev1 `link `_ py.test plugin for regression tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-regtest-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-regtest-latest?py=py34&pytest=2.6.4.dev1 - `pytest-rerunfailures `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to re-run tests to eliminate flakey failures - :target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/klrmn/pytest-rerunfailures - `pytest-runfailed `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png implement a --failed option for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/dmerejkowsky/pytest-runfailed - `pytest-runner `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png Invoke py.test as distutils command with dependency resolution. - :target: http://pytest-plugs.herokuapp.com/output/pytest-runner-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runner-latest?py=py34&pytest=2.6.4.dev1 :target: https://bitbucket.org/jaraco/pytest-runner - `pytest-sftpserver `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sftpserver-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sftpserver-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to locally test sftp server connections. - :target: http://pytest-plugs.herokuapp.com/output/pytest-sftpserver-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-sftpserver-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/ulope/pytest-sftpserver/ - `pytest-spec `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-spec-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-spec-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to display test execution output like a SPECIFICATION - :target: http://pytest-plugs.herokuapp.com/output/pytest-spec-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-spec-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/pchomik/pytest-spec - `pytest-splinter `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-splinter-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-splinter-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Splinter plugin for pytest testing framework - :target: http://pytest-plugs.herokuapp.com/output/pytest-splinter-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-splinter-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/pytest-dev/pytest-splinter - `pytest-stepwise `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-stepwise-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-stepwise-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Run a test suite one failing test at a time. - :target: http://pytest-plugs.herokuapp.com/output/pytest-stepwise-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-stepwise-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/nip3o/pytest-stepwise - `pytest-sugar `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test is a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly). - :target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/Frozenball/pytest-sugar - `pytest-timeout `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to abort hanging tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/flub/pytest-timeout/ - `pytest-twisted `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A twisted plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/schmir/pytest-twisted - `pytest-xdist `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes - :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xdist - `pytest-xprocess `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to manage external processes across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xprocess/ - `pytest-yamlwsgi `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 ? Run tests against wsgi apps defined in yaml - :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 - `pytest-zap `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png OWASP ZAP plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-zap-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-zap-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/davehunt/pytest-zap +============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== ============================================================================================================================================= + Name Py27 Py34 Home Summary +============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== ============================================================================================================================================= + `pytest-allure-adaptor `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-allure-adaptor-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-allure-adaptor-latest?py=py34&pytest=2.7.0 .. image:: github.png Plugin for py.test to generate allure xml reports + :target: http://plugincompat.herokuapp.com/output/pytest-allure-adaptor-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-allure-adaptor-latest?py=py34&pytest=2.7.0 :target: https://github.com/allure-framework/allure-python + `pytest-ansible `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ansible-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ansible-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN + :target: http://plugincompat.herokuapp.com/output/pytest-ansible-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ansible-latest?py=py34&pytest=2.7.0 :target: http://github.com/jlaska/pytest-ansible + `pytest-autochecklog `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-autochecklog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-autochecklog-latest?py=py34&pytest=2.7.0 .. image:: github.png automatically check condition and log all the checks + :target: http://plugincompat.herokuapp.com/output/pytest-autochecklog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-autochecklog-latest?py=py34&pytest=2.7.0 :target: https://github.com/steven004/python-autochecklog + `pytest-bdd `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bdd-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bdd-latest?py=py34&pytest=2.7.0 .. image:: github.png BDD for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-bdd-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bdd-latest?py=py34&pytest=2.7.0 :target: https://github.com/olegpidsadnyi/pytest-bdd + `pytest-beakerlib `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-beakerlib-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-beakerlib-latest?py=py34&pytest=2.7.0 `link `_ A pytest plugin that reports test results to the BeakerLib framework + :target: http://plugincompat.herokuapp.com/output/pytest-beakerlib-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-beakerlib-latest?py=py34&pytest=2.7.0 + `pytest-beds `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-beds-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-beds-latest?py=py34&pytest=2.7.0 .. image:: github.png Fixtures for testing Google Appengine (GAE) apps + :target: http://plugincompat.herokuapp.com/output/pytest-beds-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-beds-latest?py=py34&pytest=2.7.0 :target: https://github.com/kaste/pytest-beds + `pytest-bench `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bench-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bench-latest?py=py34&pytest=2.7.0 .. image:: github.png Benchmark utility that plugs into pytest. + :target: http://plugincompat.herokuapp.com/output/pytest-bench-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bench-latest?py=py34&pytest=2.7.0 :target: http://github.com/concordusapps/pytest-bench + `pytest-benchmark `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-benchmark-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-benchmark-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test fixture for benchmarking code + :target: http://plugincompat.herokuapp.com/output/pytest-benchmark-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-benchmark-latest?py=py34&pytest=2.7.0 :target: https://github.com/ionelmc/pytest-benchmark + `pytest-blockage `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-blockage-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-blockage-latest?py=py34&pytest=2.7.0 .. image:: github.png Disable network requests during a test run. + :target: http://plugincompat.herokuapp.com/output/pytest-blockage-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-blockage-latest?py=py34&pytest=2.7.0 :target: https://github.com/rob-b/pytest-blockage + `pytest-bpdb `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bpdb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bpdb-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plug-in to enable drop to bpdb debugger on test failure. + :target: http://plugincompat.herokuapp.com/output/pytest-bpdb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bpdb-latest?py=py34&pytest=2.7.0 :target: https://github.com/slafs/pytest-bpdb + `pytest-browsermob-proxy `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py34&pytest=2.7.0 .. image:: github.png BrowserMob proxy plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py34&pytest=2.7.0 :target: https://github.com/davehunt/pytest-browsermob-proxy + `pytest-bugzilla `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test bugzilla integration plugin + :target: http://plugincompat.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.7.0 :target: http://github.com/nibrahim/pytest_bugzilla + `pytest-cache `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs + :target: http://plugincompat.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-cache/ + `pytest-cagoule `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cagoule-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cagoule-latest?py=py34&pytest=2.7.0 .. image:: github.png Pytest plugin to only run tests affected by changes + :target: http://plugincompat.herokuapp.com/output/pytest-cagoule-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cagoule-latest?py=py34&pytest=2.7.0 :target: https://github.com/davidszotten/pytest-cagoule + `pytest-capturelog `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to capture log messages + :target: http://plugincompat.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/memedough/pytest-capturelog/overview + `pytest-catchlog `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-catchlog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-catchlog-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to catch log messages. This is a fork of pytest-capturelog. + :target: http://plugincompat.herokuapp.com/output/pytest-catchlog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-catchlog-latest?py=py34&pytest=2.7.0 :target: https://github.com/eisensheng/pytest-catchlog + `pytest-circleci `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-circleci-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-circleci-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for CircleCI + :target: http://plugincompat.herokuapp.com/output/pytest-circleci-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-circleci-latest?py=py34&pytest=2.7.0 :target: https://github.com/micktwomey/pytest-circleci + `pytest-cloud `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cloud-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cloud-latest?py=py34&pytest=2.7.0 .. image:: github.png Distributed tests planner plugin for pytest testing framework. + :target: http://plugincompat.herokuapp.com/output/pytest-cloud-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cloud-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-cloud + `pytest-codecheckers `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends) + :target: http://plugincompat.herokuapp.com/output/pytest-codecheckers-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-codecheckers-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-codecheckers/ + `pytest-colordots `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-colordots-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-colordots-latest?py=py34&pytest=2.7.0 .. image:: github.png Colorizes the progress indicators + :target: http://plugincompat.herokuapp.com/output/pytest-colordots-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-colordots-latest?py=py34&pytest=2.7.0 :target: https://github.com/svenstaro/pytest-colordots + `pytest-config `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-config-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-config-latest?py=py34&pytest=2.7.0 .. image:: github.png Base configurations and utilities for developing your Python project test suite with pytest. + :target: http://plugincompat.herokuapp.com/output/pytest-config-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-config-latest?py=py34&pytest=2.7.0 :target: https://github.com/buzzfeed/pytest_config + `pytest-contextfixture `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-contextfixture-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-contextfixture-latest?py=py34&pytest=2.7.0 .. image:: github.png Define pytest fixtures as context managers. + :target: http://plugincompat.herokuapp.com/output/pytest-contextfixture-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-contextfixture-latest?py=py34&pytest=2.7.0 :target: http://github.com/pelme/pytest-contextfixture/ + `pytest-couchdbkit `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-couchdbkit-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-couchdbkit-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test extension for per-test couchdb databases using couchdbkit + :target: http://plugincompat.herokuapp.com/output/pytest-couchdbkit-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-couchdbkit-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-couchdbkit + `pytest-cov `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cov-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cov-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing + :target: http://plugincompat.herokuapp.com/output/pytest-cov-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cov-latest?py=py34&pytest=2.7.0 :target: https://github.com/schlamar/pytest-cov + `pytest-cpp `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cpp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cpp-latest?py=py34&pytest=2.7.0 .. image:: github.png Use pytest's runner to discover and execute C++ tests + :target: http://plugincompat.herokuapp.com/output/pytest-cpp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cpp-latest?py=py34&pytest=2.7.0 :target: http://github.com/pytest-dev/pytest-cpp + `pytest-dbfixtures `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-dbfixtures-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-dbfixtures-latest?py=py34&pytest=2.7.0 .. image:: github.png Databases fixtures plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-dbfixtures-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-dbfixtures-latest?py=py34&pytest=2.7.0 :target: https://github.com/ClearcodeHQ/pytest-dbfixtures + `pytest-dbus-notification `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-dbus-notification-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-dbus-notification-latest?py=py34&pytest=2.7.0 .. image:: github.png D-BUS notifications for pytest results. + :target: http://plugincompat.herokuapp.com/output/pytest-dbus-notification-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-dbus-notification-latest?py=py34&pytest=2.7.0 :target: https://github.com/bmathieu33/pytest-dbus-notification + `pytest-describe `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-describe-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-describe-latest?py=py34&pytest=2.7.0 .. image:: github.png Describe-style plugin for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-describe-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-describe-latest?py=py34&pytest=2.7.0 :target: https://github.com/ropez/pytest-describe + `pytest-diffeo `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-diffeo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-diffeo-latest?py=py34&pytest=2.7.0 .. image:: github.png Common py.test support for Diffeo packages + :target: http://plugincompat.herokuapp.com/output/pytest-diffeo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-diffeo-latest?py=py34&pytest=2.7.0 :target: https://github.com/diffeo/pytest-diffeo + `pytest-django `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-latest?py=py34&pytest=2.7.0 `link `_ A Django plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-django-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-latest?py=py34&pytest=2.7.0 + `pytest-django-haystack `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-haystack-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-haystack-latest?py=py34&pytest=2.7.0 .. image:: github.png Cleanup your Haystack indexes between tests + :target: http://plugincompat.herokuapp.com/output/pytest-django-haystack-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-haystack-latest?py=py34&pytest=2.7.0 :target: http://github.com/rouge8/pytest-django-haystack + `pytest-django-lite `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-lite-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-lite-latest?py=py34&pytest=2.7.0 .. image:: github.png The bare minimum to integrate py.test with Django. + :target: http://plugincompat.herokuapp.com/output/pytest-django-lite-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-lite-latest?py=py34&pytest=2.7.0 :target: https://github.com/dcramer/pytest-django-lite + `pytest-django-sqlcount `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-sqlcount-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-sqlcount-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for reporting the number of SQLs executed per django testcase. + :target: http://plugincompat.herokuapp.com/output/pytest-django-sqlcount-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-sqlcount-latest?py=py34&pytest=2.7.0 :target: https://github.com/stj/pytest-django-sqlcount + `pytest-echo `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-echo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-echo-latest?py=py34&pytest=2.7.0 `link `_ pytest plugin with mechanisms for echoing environment variables, package version and generic attributes + :target: http://plugincompat.herokuapp.com/output/pytest-echo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-echo-latest?py=py34&pytest=2.7.0 + `pytest-env `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-env-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-env-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin that allows you to add environment variables. + :target: http://plugincompat.herokuapp.com/output/pytest-env-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-env-latest?py=py34&pytest=2.7.0 :target: https://github.com/MobileDynasty/pytest-env + `pytest-eradicate `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to check for commented out code + :target: http://plugincompat.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.7.0 :target: https://github.com/spil-johan/pytest-eradicate + `pytest-figleaf `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test figleaf coverage plugin + :target: http://plugincompat.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-figleaf + `pytest-fixture-tools `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.7.0 ? Plugin for pytest which provides tools for fixtures + :target: http://plugincompat.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.7.0 + `pytest-flakes `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to check source code with pyflakes + :target: http://plugincompat.herokuapp.com/output/pytest-flakes-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-flakes-latest?py=py34&pytest=2.7.0 :target: https://github.com/fschulze/pytest-flakes + `pytest-flask `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-flask-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-flask-latest?py=py34&pytest=2.7.0 .. image:: github.png A set of py.test fixtures to test Flask applications. + :target: http://plugincompat.herokuapp.com/output/pytest-flask-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-flask-latest?py=py34&pytest=2.7.0 :target: https://github.com/vitalk/pytest-flask + `pytest-greendots `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-greendots-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-greendots-latest?py=py34&pytest=2.7.0 ? Green progress dots + :target: http://plugincompat.herokuapp.com/output/pytest-greendots-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-greendots-latest?py=py34&pytest=2.7.0 + `pytest-growl `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-growl-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-growl-latest?py=py34&pytest=2.7.0 ? Growl notifications for pytest results. + :target: http://plugincompat.herokuapp.com/output/pytest-growl-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-growl-latest?py=py34&pytest=2.7.0 + `pytest-httpbin `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-httpbin-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-httpbin-latest?py=py34&pytest=2.7.0 .. image:: github.png Easily test your HTTP library against a local copy of httpbin + :target: http://plugincompat.herokuapp.com/output/pytest-httpbin-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-httpbin-latest?py=py34&pytest=2.7.0 :target: https://github.com/kevin1024/pytest-httpbin + `pytest-httpretty `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-httpretty-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-httpretty-latest?py=py34&pytest=2.7.0 .. image:: github.png A thin wrapper of HTTPretty for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-httpretty-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-httpretty-latest?py=py34&pytest=2.7.0 :target: http://github.com/papaeye/pytest-httpretty + `pytest-incremental `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-incremental-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-incremental-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png an incremental test runner (pytest plugin) + :target: http://plugincompat.herokuapp.com/output/pytest-incremental-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-incremental-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/schettino72/pytest-incremental + `pytest-instafail `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-instafail-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-instafail-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to show failures instantly + :target: http://plugincompat.herokuapp.com/output/pytest-instafail-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-instafail-latest?py=py34&pytest=2.7.0 :target: https://github.com/jpvanhal/pytest-instafail + `pytest-ipdb `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ipdb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ipdb-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plug-in to enable drop to ipdb debugger on test failure. + :target: http://plugincompat.herokuapp.com/output/pytest-ipdb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ipdb-latest?py=py34&pytest=2.7.0 :target: https://github.com/mverteuil/pytest-ipdb + `pytest-ipynb `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ipynb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ipynb-latest?py=py34&pytest=2.7.0 .. image:: github.png Use pytest's runner to discover and execute tests as cells of IPython notebooks + :target: http://plugincompat.herokuapp.com/output/pytest-ipynb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ipynb-latest?py=py34&pytest=2.7.0 :target: http://github.com/zonca/pytest-ipynb + `pytest-jira `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-jira-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-jira-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test JIRA integration plugin, using markers + :target: http://plugincompat.herokuapp.com/output/pytest-jira-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-jira-latest?py=py34&pytest=2.7.0 :target: http://github.com/jlaska/pytest_jira + `pytest-knows `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-knows-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-knows-latest?py=py34&pytest=2.7.0 .. image:: github.png A pytest plugin that can automaticly skip test case based on dependence info calculated by trace + :target: http://plugincompat.herokuapp.com/output/pytest-knows-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-knows-latest?py=py34&pytest=2.7.0 :target: https://github.com/mapix/ptknows + `pytest-konira `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-konira-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-konira-latest?py=py34&pytest=2.7.0 .. image:: github.png Run Konira DSL tests with py.test + :target: http://plugincompat.herokuapp.com/output/pytest-konira-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-konira-latest?py=py34&pytest=2.7.0 :target: http://github.com/alfredodeza/pytest-konira + `pytest-localserver `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-localserver-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-localserver-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to test server connections locally. + :target: http://plugincompat.herokuapp.com/output/pytest-localserver-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-localserver-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/basti/pytest-localserver/ + `pytest-marker-bugzilla `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test bugzilla integration plugin, using markers + :target: http://plugincompat.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py34&pytest=2.7.0 :target: http://github.com/eanxgeek/pytest_marker_bugzilla + `pytest-markfiltration `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-markfiltration-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-markfiltration-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN + :target: http://plugincompat.herokuapp.com/output/pytest-markfiltration-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-markfiltration-latest?py=py34&pytest=2.7.0 :target: https://github.com/adamgoucher/pytest-markfiltration + `pytest-marks `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-marks-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-marks-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN + :target: http://plugincompat.herokuapp.com/output/pytest-marks-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-marks-latest?py=py34&pytest=2.7.0 :target: https://github.com/adamgoucher/pytest-marks + `pytest-mock `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-mock-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-mock-latest?py=py34&pytest=2.7.0 .. image:: github.png Thin-wrapper around the mock package for easier use with py.test + :target: http://plugincompat.herokuapp.com/output/pytest-mock-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-mock-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-mock/ + `pytest-monkeyplus `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-monkeyplus-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-monkeyplus-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest's monkeypatch subclass with extra functionalities + :target: http://plugincompat.herokuapp.com/output/pytest-monkeyplus-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-monkeyplus-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hsoft/pytest-monkeyplus/ + `pytest-mozwebqa `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-mozwebqa-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-mozwebqa-latest?py=py34&pytest=2.7.0 .. image:: github.png Mozilla WebQA plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-mozwebqa-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-mozwebqa-latest?py=py34&pytest=2.7.0 :target: https://github.com/mozilla/pytest-mozwebqa + `pytest-multihost `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-multihost-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-multihost-latest?py=py34&pytest=2.7.0 `link `_ Utility for writing multi-host tests for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-multihost-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-multihost-latest?py=py34&pytest=2.7.0 + `pytest-oerp `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-oerp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-oerp-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to test OpenERP modules + :target: http://plugincompat.herokuapp.com/output/pytest-oerp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-oerp-latest?py=py34&pytest=2.7.0 :target: http://github.com/santagada/pytest-oerp/ + `pytest-oot `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-oot-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-oot-latest?py=py34&pytest=2.7.0 `link `_ Run object-oriented tests in a simple format + :target: http://plugincompat.herokuapp.com/output/pytest-oot-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-oot-latest?py=py34&pytest=2.7.0 + `pytest-optional `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-optional-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-optional-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png include/exclude values of fixtures in pytest + :target: http://plugincompat.herokuapp.com/output/pytest-optional-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-optional-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/maho/pytest-optional + `pytest-ordering `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ordering-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ordering-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to run your tests in a specific order + :target: http://plugincompat.herokuapp.com/output/pytest-ordering-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ordering-latest?py=py34&pytest=2.7.0 :target: https://github.com/ftobia/pytest-ordering + `pytest-osxnotify `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-osxnotify-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-osxnotify-latest?py=py34&pytest=2.7.0 .. image:: github.png OS X notifications for py.test results. + :target: http://plugincompat.herokuapp.com/output/pytest-osxnotify-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-osxnotify-latest?py=py34&pytest=2.7.0 :target: https://github.com/dbader/pytest-osxnotify + `pytest-paste-config `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.7.0 ? Allow setting the path to a paste config file + :target: http://plugincompat.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.7.0 + `pytest-pep257 `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pep257-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pep257-latest?py=py34&pytest=2.7.0 ? py.test plugin for pep257 + :target: http://plugincompat.herokuapp.com/output/pytest-pep257-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pep257-latest?py=py34&pytest=2.7.0 + `pytest-pep8 `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to check PEP8 requirements + :target: http://plugincompat.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-pep8/ + `pytest-pipeline `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.7.0 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines + :target: http://plugincompat.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.7.0 :target: https://github.com/bow/pytest_pipeline + `pytest-poo `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.7.0 .. image:: github.png Visualize your crappy tests + :target: http://plugincompat.herokuapp.com/output/pytest-poo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-poo-latest?py=py34&pytest=2.7.0 :target: http://github.com/pelme/pytest-poo + `pytest-poo-fail `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-fail-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-fail-latest?py=py34&pytest=2.7.0 .. image:: github.png Visualize your failed tests with poo + :target: http://plugincompat.herokuapp.com/output/pytest-poo-fail-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-poo-fail-latest?py=py34&pytest=2.7.0 :target: http://github.com/alyssa.barela/pytest-poo-fail + `pytest-pycharm `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pycharm-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pycharm-latest?py=py34&pytest=2.7.0 .. image:: github.png Plugin for py.test to enter PyCharm debugger on uncaught exceptions + :target: http://plugincompat.herokuapp.com/output/pytest-pycharm-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pycharm-latest?py=py34&pytest=2.7.0 :target: https://github.com/jlubcke/pytest-pycharm + `pytest-pydev `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pydev-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pydev-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to connect to a remote debug server with PyDev or PyCharm. + :target: http://plugincompat.herokuapp.com/output/pytest-pydev-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pydev-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/basti/pytest-pydev/ + `pytest-pyq `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pyq-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pyq-latest?py=py34&pytest=2.7.0 `link `_ Pytest fixture "q" for pyq + :target: http://plugincompat.herokuapp.com/output/pytest-pyq-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pyq-latest?py=py34&pytest=2.7.0 + `pytest-pythonpath `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pythonpath-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pythonpath-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin for adding to the PYTHONPATH from command line or configs. + :target: http://plugincompat.herokuapp.com/output/pytest-pythonpath-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pythonpath-latest?py=py34&pytest=2.7.0 :target: https://github.com/bigsassy/pytest-pythonpath + `pytest-qt `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-qt-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-qt-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest support for PyQt and PySide applications + :target: http://plugincompat.herokuapp.com/output/pytest-qt-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-qt-latest?py=py34&pytest=2.7.0 :target: http://github.com/pytest-dev/pytest-qt + `pytest-quickcheck `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-quickcheck-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-quickcheck-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to generate random data inspired by QuickCheck + :target: http://plugincompat.herokuapp.com/output/pytest-quickcheck-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-quickcheck-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/t2y/pytest-quickcheck/ + `pytest-rage `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-rage-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-rage-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to implement PEP712 + :target: http://plugincompat.herokuapp.com/output/pytest-rage-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-rage-latest?py=py34&pytest=2.7.0 :target: http://github.com/santagada/pytest-rage/ + `pytest-raisesregexp `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-raisesregexp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-raisesregexp-latest?py=py34&pytest=2.7.0 .. image:: github.png Simple pytest plugin to look for regex in Exceptions + :target: http://plugincompat.herokuapp.com/output/pytest-raisesregexp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-raisesregexp-latest?py=py34&pytest=2.7.0 :target: https://github.com/Walkman/pytest_raisesregexp + `pytest-random `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-random-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-random-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to randomize tests + :target: http://plugincompat.herokuapp.com/output/pytest-random-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-random-latest?py=py34&pytest=2.7.0 :target: https://github.com/klrmn/pytest-random + `pytest-readme `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-readme-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-readme-latest?py=py34&pytest=2.7.0 .. image:: github.png Test your README.md file + :target: http://plugincompat.herokuapp.com/output/pytest-readme-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-readme-latest?py=py34&pytest=2.7.0 :target: https://github.com/boxed/pytest-readme + `pytest-regtest `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-regtest-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-regtest-latest?py=py34&pytest=2.7.0 `link `_ py.test plugin for regression tests + :target: http://plugincompat.herokuapp.com/output/pytest-regtest-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-regtest-latest?py=py34&pytest=2.7.0 + `pytest-remove-stale-bytecode `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-remove-stale-bytecode-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-remove-stale-bytecode-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to remove stale byte code files. + :target: http://plugincompat.herokuapp.com/output/pytest-remove-stale-bytecode-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-remove-stale-bytecode-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/gocept/pytest-remove-stale-bytecode/ + `pytest-rerunfailures `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-rerunfailures-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-rerunfailures-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to re-run tests to eliminate flakey failures + :target: http://plugincompat.herokuapp.com/output/pytest-rerunfailures-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-rerunfailures-latest?py=py34&pytest=2.7.0 :target: https://github.com/klrmn/pytest-rerunfailures + `pytest-runfailed `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-runfailed-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-runfailed-latest?py=py34&pytest=2.7.0 .. image:: github.png implement a --failed option for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-runfailed-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-runfailed-latest?py=py34&pytest=2.7.0 :target: http://github.com/dmerejkowsky/pytest-runfailed + `pytest-runner `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-runner-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-runner-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png Invoke py.test as distutils command with dependency resolution. + :target: http://plugincompat.herokuapp.com/output/pytest-runner-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-runner-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/jaraco/pytest-runner + `pytest-services `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-services-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-services-latest?py=py34&pytest=2.7.0 .. image:: github.png Services plugin for pytest testing framework + :target: http://plugincompat.herokuapp.com/output/pytest-services-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-services-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-services + `pytest-sftpserver `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sftpserver-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sftpserver-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to locally test sftp server connections. + :target: http://plugincompat.herokuapp.com/output/pytest-sftpserver-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sftpserver-latest?py=py34&pytest=2.7.0 :target: http://github.com/ulope/pytest-sftpserver/ + `pytest-smartcov `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-smartcov-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-smartcov-latest?py=py34&pytest=2.7.0 .. image:: github.png Smart coverage plugin for pytest. + :target: http://plugincompat.herokuapp.com/output/pytest-smartcov-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-smartcov-latest?py=py34&pytest=2.7.0 :target: https://github.com/carljm/pytest-smartcov/ + `pytest-sourceorder `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sourceorder-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sourceorder-latest?py=py34&pytest=2.7.0 `link `_ Test-ordering plugin for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-sourceorder-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sourceorder-latest?py=py34&pytest=2.7.0 + `pytest-spec `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-spec-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-spec-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to display test execution output like a SPECIFICATION + :target: http://plugincompat.herokuapp.com/output/pytest-spec-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-spec-latest?py=py34&pytest=2.7.0 :target: https://github.com/pchomik/pytest-spec + `pytest-splinter `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-splinter-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-splinter-latest?py=py34&pytest=2.7.0 .. image:: github.png Splinter plugin for pytest testing framework + :target: http://plugincompat.herokuapp.com/output/pytest-splinter-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-splinter-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-splinter + `pytest-stepwise `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-stepwise-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-stepwise-latest?py=py34&pytest=2.7.0 .. image:: github.png Run a test suite one failing test at a time. + :target: http://plugincompat.herokuapp.com/output/pytest-stepwise-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-stepwise-latest?py=py34&pytest=2.7.0 :target: https://github.com/nip3o/pytest-stepwise + `pytest-sugar `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sugar-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sugar-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test is a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly). + :target: http://plugincompat.herokuapp.com/output/pytest-sugar-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sugar-latest?py=py34&pytest=2.7.0 :target: https://github.com/Frozenball/pytest-sugar + `pytest-timeout `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-timeout-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-timeout-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to abort hanging tests + :target: http://plugincompat.herokuapp.com/output/pytest-timeout-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-timeout-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/flub/pytest-timeout/ + `pytest-tornado `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-tornado-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-tornado-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. + :target: http://plugincompat.herokuapp.com/output/pytest-tornado-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-tornado-latest?py=py34&pytest=2.7.0 :target: https://github.com/eugeniy/pytest-tornado + `pytest-translations `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-translations-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-translations-latest?py=py34&pytest=2.7.0 .. image:: github.png Test your translation files + :target: http://plugincompat.herokuapp.com/output/pytest-translations-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-translations-latest?py=py34&pytest=2.7.0 :target: https://github.com/thermondo/pytest-translations + `pytest-twisted `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.7.0 .. image:: github.png A twisted plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.7.0 :target: https://github.com/schmir/pytest-twisted + `pytest-unmarked `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-unmarked-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-unmarked-latest?py=py34&pytest=2.7.0 .. image:: github.png Run only unmarked tests + :target: http://plugincompat.herokuapp.com/output/pytest-unmarked-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-unmarked-latest?py=py34&pytest=2.7.0 :target: http://github.com/alyssa.barela/pytest-unmarked + `pytest-watch `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-watch-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-watch-latest?py=py34&pytest=2.7.0 .. image:: github.png Local continuous test runner with pytest and watchdog. + :target: http://plugincompat.herokuapp.com/output/pytest-watch-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-watch-latest?py=py34&pytest=2.7.0 :target: http://github.com/joeyespo/pytest-watch + `pytest-xdist `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes + :target: http://plugincompat.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-xdist + `pytest-xprocess `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to manage external processes across test runs + :target: http://plugincompat.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-xprocess/ + `pytest-yamlwsgi `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.7.0 ? Run tests against wsgi apps defined in yaml + :target: http://plugincompat.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.7.0 + `pytest-zap `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.7.0 .. image:: github.png OWASP ZAP plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-zap-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-zap-latest?py=py34&pytest=2.7.0 :target: https://github.com/davehunt/pytest-zap -==================================================================================== ================================================================================================================= ================================================================================================================= =========================================================================== ============================================================================================================================================= +============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== ============================================================================================================================================= -*(Updated on 2014-09-27)* +*(Updated on 2015-02-28)* diff -r c3dd3f237dd4cf8cbfa61ce1522f979f77d6e7b7 -r 5294eee465a2b5c072b1e191d2cb2540a7c9d962 doc/en/plugins_index/plugins_index.py --- a/doc/en/plugins_index/plugins_index.py +++ b/doc/en/plugins_index/plugins_index.py @@ -10,7 +10,7 @@ versions from PyPI. Also includes plugin compatibility between different python and pytest versions, -obtained from http://pytest-plugs.herokuapp.com. +obtained from http://plugincompat.herokuapp.com. """ from __future__ import print_function from collections import namedtuple @@ -61,7 +61,7 @@ yield name, str(loose_version) -def obtain_plugins_table(plugins, client, verbose): +def obtain_plugins_table(plugins, client, verbose, pytest_ver): """ Returns information to populate a table of plugins, their versions, authors, etc. @@ -73,7 +73,11 @@ :param plugins: list of (name, version) :param client: ServerProxy :param verbose: print plugin name and version as they are fetch + :param pytest_ver: pytest version to use. """ + if pytest_ver is None: + pytest_ver = pytest.__version__ + def get_repo_markup(repo): """ obtains appropriate markup for the given repository, as two lines @@ -107,9 +111,8 @@ rows = [] ColumnData = namedtuple('ColumnData', 'text link') headers = ['Name', 'Py27', 'Py34', 'Home', 'Summary'] - pytest_version = pytest.__version__ repositories = obtain_override_repositories() - print('Generating plugins_index page (pytest-{0})'.format(pytest_version)) + print('Generating plugins_index page (pytest-{0})'.format(pytest_ver)) plugins = list(plugins) for index, (package_name, version) in enumerate(plugins): if verbose: @@ -118,7 +121,7 @@ release_data = client.release_data(package_name, version) common_params = dict( - site='http://pytest-plugs.herokuapp.com', + site='http://plugincompat.herokuapp.com', name=package_name, version=version) @@ -131,9 +134,9 @@ image_url += '?py={py}&pytest={pytest}' row = ( ColumnData(package_name, release_data['package_url']), - ColumnData(image_url.format(py='py27', pytest=pytest_version), + ColumnData(image_url.format(py='py27', pytest=pytest_ver), None), - ColumnData(image_url.format(py='py34', pytest=pytest_version), + ColumnData(image_url.format(py='py34', pytest=pytest_ver), None), ColumnData( repo_markup_1, @@ -150,9 +153,9 @@ row = ( ColumnData('', None), - ColumnData(output_url.format(py='py27', pytest=pytest_version), + ColumnData(output_url.format(py='py27', pytest=pytest_ver), None), - ColumnData(output_url.format(py='py34', pytest=pytest_version), + ColumnData(output_url.format(py='py34', pytest=pytest_ver), None), ColumnData(repo_markup_2, None), ColumnData('', None), @@ -184,13 +187,14 @@ } -def generate_plugins_index_from_table(filename, headers, rows): +def generate_plugins_index_from_table(filename, headers, rows, pytest_ver): """ Generates a RST file with the table data given. :param filename: output filename :param headers: see `obtain_plugins_table` :param rows: see `obtain_plugins_table` + :param pytest_ver: see `obtain_plugins_table` """ # creates a list of rows, each being a str containing appropriate column # text and link @@ -215,7 +219,7 @@ with open(filename, 'w') as f: # header - header_text = HEADER.format(pytest_version=pytest.__version__) + header_text = HEADER.format(pytest_version=pytest_ver) print(header_text, file=f) print(file=f) @@ -240,7 +244,7 @@ print('*(Updated on %s)*' % today, file=f) -def generate_plugins_index(client, filename, verbose): +def generate_plugins_index(client, filename, verbose, pytest_ver): """ Generates an RST file with a table of the latest pytest plugins found in PyPI. @@ -248,10 +252,12 @@ :param client: ServerProxy :param filename: output filename :param verbose: print name and version of each plugin as they are fetch + :param pytest_ver: pytest version to use; if not given, use current pytest + version. """ plugins = get_latest_versions(iter_plugins(client)) - headers, rows = obtain_plugins_table(plugins, client, verbose) - generate_plugins_index_from_table(filename, headers, rows) + headers, rows = obtain_plugins_table(plugins, client, verbose, pytest_ver) + generate_plugins_index_from_table(filename, headers, rows, pytest_ver) def main(argv): @@ -270,10 +276,12 @@ help='url of PyPI server to obtain data from [default: %default]') parser.add_option('-v', '--verbose', default=False, action='store_true', help='verbose output') + parser.add_option('--pytest-ver', default=None, action='store', + help='generate index for this pytest version (default current version)') (options, _) = parser.parse_args(argv[1:]) client = get_proxy(options.url) - generate_plugins_index(client, options.filename, options.verbose) + generate_plugins_index(client, options.filename, options.verbose, options.pytest_ver) print() print('%s updated.' % options.filename) @@ -291,7 +299,7 @@ 3.3. A complete listing can also be found at -`pytest-plugs `_, which contains tests +`plugincompat `_, which contains tests status against other py.test releases. ''' Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From commits-noreply at bitbucket.org Sat Feb 28 21:33:01 2015 From: commits-noreply at bitbucket.org (commits-noreply at bitbucket.org) Date: Sat, 28 Feb 2015 20:33:01 -0000 Subject: [Pytest-commit] commit/pytest: bubenkoff: Merged in plugincompat-move (pull request #256) Message-ID: <20150228203301.9119.88959@app04.ash-private.bitbucket.org> 1 new commit in pytest: https://bitbucket.org/pytest-dev/pytest/commits/163964f4f0f4/ Changeset: 163964f4f0f4 User: bubenkoff Date: 2015-02-28 20:32:57+00:00 Summary: Merged in plugincompat-move (pull request #256) moved pytest-plugs to plugincompat Affected #: 3 files diff -r c3dd3f237dd4cf8cbfa61ce1522f979f77d6e7b7 -r 163964f4f0f48204f9f42d080778f23d6673f0b0 doc/en/plugins.txt --- a/doc/en/plugins.txt +++ b/doc/en/plugins.txt @@ -112,7 +112,7 @@ To see a complete list of all plugins with their latest testing status against different py.test and Python versions, please visit -`pytest-plugs `_. +`plugincompat `_. You may also discover more plugins through a `pytest- pypi.python.org search`_. diff -r c3dd3f237dd4cf8cbfa61ce1522f979f77d6e7b7 -r 163964f4f0f48204f9f42d080778f23d6673f0b0 doc/en/plugins_index/index.txt --- a/doc/en/plugins_index/index.txt +++ b/doc/en/plugins_index/index.txt @@ -4,168 +4,224 @@ =========================== The table below contains a listing of plugins found in PyPI and -their status when tested using py.test **2.6.4.dev1** and python 2.7 and +their status when tested using py.test **2.7.0** and python 2.7 and 3.3. A complete listing can also be found at -`pytest-plugs `_, which contains tests +`plugincompat `_, which contains tests status against other py.test releases. -==================================================================================== ================================================================================================================= ================================================================================================================= =========================================================================== ============================================================================================================================================= - Name Py27 Py34 Home Summary -==================================================================================== ================================================================================================================= ================================================================================================================= =========================================================================== ============================================================================================================================================= - `pytest-allure-adaptor `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-allure-adaptor-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-allure-adaptor-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Plugin for py.test to generate allure xml reports - :target: http://pytest-plugs.herokuapp.com/output/pytest-allure-adaptor-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-allure-adaptor-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/allure-framework/allure-python - `pytest-bdd `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png BDD for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/olegpidsadnyi/pytest-bdd - `pytest-beds `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-beds-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-beds-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Fixtures for testing Google Appengine (GAE) apps - :target: http://pytest-plugs.herokuapp.com/output/pytest-beds-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-beds-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/kaste/pytest-beds - `pytest-bench `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Benchmark utility that plugs into pytest. - :target: http://pytest-plugs.herokuapp.com/output/pytest-bench-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bench-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/concordusapps/pytest-bench - `pytest-blockage `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Disable network requests during a test run. - :target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/rob-b/pytest-blockage - `pytest-browsermob-proxy `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png BrowserMob proxy plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/davehunt/pytest-browsermob-proxy - `pytest-bugzilla `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test bugzilla integration plugin - :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nibrahim/pytest_bugzilla - `pytest-cache `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-cache/ - `pytest-capturelog `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to capture log messages - :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/memedough/pytest-capturelog/overview - `pytest-codecheckers `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends) - :target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-codecheckers/ - `pytest-config `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-config-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-config-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Base configurations and utilities for developing your Python project test suite with pytest. - :target: http://pytest-plugs.herokuapp.com/output/pytest-config-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-config-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/buzzfeed/pytest_config - `pytest-contextfixture `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Define pytest fixtures as context managers. - :target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/pelme/pytest-contextfixture/ - `pytest-couchdbkit `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test extension for per-test couchdb databases using couchdbkit - :target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-couchdbkit - `pytest-cov `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing - :target: http://pytest-plugs.herokuapp.com/output/pytest-cov-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cov-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/schlamar/pytest-cov - `pytest-cpp `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cpp-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cpp-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Use pytest's runner to discover and execute C++ tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-cpp-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cpp-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nicoddemus/pytest-cpp - `pytest-dbfixtures `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Databases fixtures plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/ClearcodeHQ/pytest-dbfixtures - `pytest-dbus-notification `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbus-notification-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbus-notification-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png D-BUS notifications for pytest results. - :target: http://pytest-plugs.herokuapp.com/output/pytest-dbus-notification-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-dbus-notification-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bmathieu33/pytest-dbus-notification - `pytest-describe `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-describe-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-describe-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Describe-style plugin for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-describe-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-describe-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/ropez/pytest-describe - `pytest-diffeo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-diffeo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-diffeo-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Common py.test support for Diffeo packages - :target: http://pytest-plugs.herokuapp.com/output/pytest-diffeo-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-diffeo-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/diffeo/pytest-diffeo - `pytest-django `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-latest?py=py34&pytest=2.6.4.dev1 `link `_ A Django plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-django-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-latest?py=py34&pytest=2.6.4.dev1 - `pytest-django-haystack `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-haystack-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-haystack-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Cleanup your Haystack indexes between tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-django-haystack-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-haystack-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/rouge8/pytest-django-haystack - `pytest-django-lite `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png The bare minimum to integrate py.test with Django. - :target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/dcramer/pytest-django-lite - `pytest-echo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-echo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-echo-latest?py=py34&pytest=2.6.4.dev1 `link `_ pytest plugin with mechanisms for echoing environment variables, package version and generic attributes - :target: http://pytest-plugs.herokuapp.com/output/pytest-echo-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-echo-latest?py=py34&pytest=2.6.4.dev1 - `pytest-eradicate `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check for commented out code - :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/spil-johan/pytest-eradicate - `pytest-figleaf `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test figleaf coverage plugin - :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-figleaf - `pytest-fixture-tools `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 ? Plugin for pytest which provides tools for fixtures - :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.6.4.dev1 - `pytest-flakes `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to check source code with pyflakes - :target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/fschulze/pytest-flakes - `pytest-flask `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flask-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flask-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A set of py.test fixtures to test Flask applications. - :target: http://pytest-plugs.herokuapp.com/output/pytest-flask-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-flask-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/vitalk/pytest-flask - `pytest-greendots `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-latest?py=py34&pytest=2.6.4.dev1 ? Green progress dots - :target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-latest?py=py34&pytest=2.6.4.dev1 - `pytest-growl `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-latest?py=py34&pytest=2.6.4.dev1 ? Growl notifications for pytest results. - :target: http://pytest-plugs.herokuapp.com/output/pytest-growl-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-growl-latest?py=py34&pytest=2.6.4.dev1 - `pytest-httpbin `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpbin-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpbin-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Easily test your HTTP library against a local copy of httpbin - :target: http://pytest-plugs.herokuapp.com/output/pytest-httpbin-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-httpbin-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/kevin1024/pytest-httpbin - `pytest-httpretty `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpretty-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpretty-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A thin wrapper of HTTPretty for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-httpretty-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-httpretty-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/papaeye/pytest-httpretty - `pytest-incremental `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png an incremental test runner (pytest plugin) - :target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-latest?py=py34&pytest=2.6.4.dev1 :target: https://bitbucket.org/schettino72/pytest-incremental - `pytest-instafail `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to show failures instantly - :target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/jpvanhal/pytest-instafail - `pytest-ipdb `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A py.test plug-in to enable drop to ipdb debugger on test failure. - :target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/mverteuil/pytest-ipdb - `pytest-jira `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test JIRA integration plugin, using markers - :target: http://pytest-plugs.herokuapp.com/output/pytest-jira-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-jira-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/jlaska/pytest_jira - `pytest-knows `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-knows-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-knows-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A pytest plugin that can automaticly skip test case based on dependence info calculated by trace - :target: http://pytest-plugs.herokuapp.com/output/pytest-knows-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-knows-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/mapix/ptknows - `pytest-konira `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Run Konira DSL tests with py.test - :target: http://pytest-plugs.herokuapp.com/output/pytest-konira-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-konira-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/alfredodeza/pytest-konira - `pytest-localserver `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to test server connections locally. - :target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/basti/pytest-localserver/ - `pytest-marker-bugzilla `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test bugzilla integration plugin, using markers - :target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/eanxgeek/pytest_marker_bugzilla - `pytest-markfiltration `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png UNKNOWN - :target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/adamgoucher/pytest-markfiltration - `pytest-marks `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png UNKNOWN - :target: http://pytest-plugs.herokuapp.com/output/pytest-marks-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marks-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/adamgoucher/pytest-marks - `pytest-mock `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mock-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mock-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Thin-wrapper around the mock package for easier use with py.test - :target: http://pytest-plugs.herokuapp.com/output/pytest-mock-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-mock-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/nicoddemus/pytest-mock/ - `pytest-monkeyplus `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest's monkeypatch subclass with extra functionalities - :target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/hsoft/pytest-monkeyplus/ - `pytest-mozwebqa `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Mozilla WebQA plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/davehunt/pytest-mozwebqa - `pytest-oerp `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to test OpenERP modules - :target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/santagada/pytest-oerp/ - `pytest-ordering `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ordering-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ordering-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to run your tests in a specific order - :target: http://pytest-plugs.herokuapp.com/output/pytest-ordering-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-ordering-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/ftobia/pytest-ordering - `pytest-osxnotify `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png OS X notifications for py.test results. - :target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/dbader/pytest-osxnotify - `pytest-paste-config `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 ? Allow setting the path to a paste config file - :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.6.4.dev1 - `pytest-pep8 `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to check PEP8 requirements - :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-pep8/ - `pytest-pipeline `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines - :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bow/pytest_pipeline - `pytest-poo `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Visualize your crappy tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-poo-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-poo-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/pelme/pytest-poo - `pytest-pycharm `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pycharm-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pycharm-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Plugin for py.test to enter PyCharm debugger on uncaught exceptions - :target: http://pytest-plugs.herokuapp.com/output/pytest-pycharm-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pycharm-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/jlubcke/pytest-pycharm - `pytest-pydev `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to connect to a remote debug server with PyDev or PyCharm. - :target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/basti/pytest-pydev/ - `pytest-pythonpath `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pythonpath-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pythonpath-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin for adding to the PYTHONPATH from command line or configs. - :target: http://pytest-plugs.herokuapp.com/output/pytest-pythonpath-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pythonpath-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/bigsassy/pytest-pythonpath - `pytest-qt `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest support for PyQt and PySide applications - :target: http://pytest-plugs.herokuapp.com/output/pytest-qt-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-qt-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/nicoddemus/pytest-qt - `pytest-quickcheck `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to generate random data inspired by QuickCheck - :target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/t2y/pytest-quickcheck/ - `pytest-rage `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to implement PEP712 - :target: http://pytest-plugs.herokuapp.com/output/pytest-rage-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rage-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/santagada/pytest-rage/ - `pytest-raisesregexp `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-raisesregexp-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-raisesregexp-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Simple pytest plugin to look for regex in Exceptions - :target: http://pytest-plugs.herokuapp.com/output/pytest-raisesregexp-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-raisesregexp-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/Walkman/pytest_raisesregexp - `pytest-random `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to randomize tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-random-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-random-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/klrmn/pytest-random - `pytest-regtest `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-regtest-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-regtest-latest?py=py34&pytest=2.6.4.dev1 `link `_ py.test plugin for regression tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-regtest-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-regtest-latest?py=py34&pytest=2.6.4.dev1 - `pytest-rerunfailures `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to re-run tests to eliminate flakey failures - :target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/klrmn/pytest-rerunfailures - `pytest-runfailed `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png implement a --failed option for pytest - :target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/dmerejkowsky/pytest-runfailed - `pytest-runner `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png Invoke py.test as distutils command with dependency resolution. - :target: http://pytest-plugs.herokuapp.com/output/pytest-runner-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runner-latest?py=py34&pytest=2.6.4.dev1 :target: https://bitbucket.org/jaraco/pytest-runner - `pytest-sftpserver `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sftpserver-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sftpserver-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test plugin to locally test sftp server connections. - :target: http://pytest-plugs.herokuapp.com/output/pytest-sftpserver-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-sftpserver-latest?py=py34&pytest=2.6.4.dev1 :target: http://github.com/ulope/pytest-sftpserver/ - `pytest-spec `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-spec-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-spec-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png pytest plugin to display test execution output like a SPECIFICATION - :target: http://pytest-plugs.herokuapp.com/output/pytest-spec-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-spec-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/pchomik/pytest-spec - `pytest-splinter `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-splinter-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-splinter-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Splinter plugin for pytest testing framework - :target: http://pytest-plugs.herokuapp.com/output/pytest-splinter-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-splinter-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/pytest-dev/pytest-splinter - `pytest-stepwise `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-stepwise-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-stepwise-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png Run a test suite one failing test at a time. - :target: http://pytest-plugs.herokuapp.com/output/pytest-stepwise-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-stepwise-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/nip3o/pytest-stepwise - `pytest-sugar `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png py.test is a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly). - :target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/Frozenball/pytest-sugar - `pytest-timeout `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test plugin to abort hanging tests - :target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/flub/pytest-timeout/ - `pytest-twisted `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png A twisted plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/schmir/pytest-twisted - `pytest-xdist `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes - :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xdist - `pytest-xprocess `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 .. image:: bitbucket.png pytest plugin to manage external processes across test runs - :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.6.4.dev1 :target: http://bitbucket.org/pytest-dev/pytest-xprocess/ - `pytest-yamlwsgi `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 ? Run tests against wsgi apps defined in yaml - :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.6.4.dev1 - `pytest-zap `_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.6.4.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.6.4.dev1 .. image:: github.png OWASP ZAP plugin for py.test. - :target: http://pytest-plugs.herokuapp.com/output/pytest-zap-latest?py=py27&pytest=2.6.4.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-zap-latest?py=py34&pytest=2.6.4.dev1 :target: https://github.com/davehunt/pytest-zap +============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== ============================================================================================================================================= + Name Py27 Py34 Home Summary +============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== ============================================================================================================================================= + `pytest-allure-adaptor `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-allure-adaptor-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-allure-adaptor-latest?py=py34&pytest=2.7.0 .. image:: github.png Plugin for py.test to generate allure xml reports + :target: http://plugincompat.herokuapp.com/output/pytest-allure-adaptor-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-allure-adaptor-latest?py=py34&pytest=2.7.0 :target: https://github.com/allure-framework/allure-python + `pytest-ansible `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ansible-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ansible-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN + :target: http://plugincompat.herokuapp.com/output/pytest-ansible-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ansible-latest?py=py34&pytest=2.7.0 :target: http://github.com/jlaska/pytest-ansible + `pytest-autochecklog `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-autochecklog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-autochecklog-latest?py=py34&pytest=2.7.0 .. image:: github.png automatically check condition and log all the checks + :target: http://plugincompat.herokuapp.com/output/pytest-autochecklog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-autochecklog-latest?py=py34&pytest=2.7.0 :target: https://github.com/steven004/python-autochecklog + `pytest-bdd `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bdd-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bdd-latest?py=py34&pytest=2.7.0 .. image:: github.png BDD for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-bdd-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bdd-latest?py=py34&pytest=2.7.0 :target: https://github.com/olegpidsadnyi/pytest-bdd + `pytest-beakerlib `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-beakerlib-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-beakerlib-latest?py=py34&pytest=2.7.0 `link `_ A pytest plugin that reports test results to the BeakerLib framework + :target: http://plugincompat.herokuapp.com/output/pytest-beakerlib-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-beakerlib-latest?py=py34&pytest=2.7.0 + `pytest-beds `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-beds-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-beds-latest?py=py34&pytest=2.7.0 .. image:: github.png Fixtures for testing Google Appengine (GAE) apps + :target: http://plugincompat.herokuapp.com/output/pytest-beds-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-beds-latest?py=py34&pytest=2.7.0 :target: https://github.com/kaste/pytest-beds + `pytest-bench `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bench-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bench-latest?py=py34&pytest=2.7.0 .. image:: github.png Benchmark utility that plugs into pytest. + :target: http://plugincompat.herokuapp.com/output/pytest-bench-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bench-latest?py=py34&pytest=2.7.0 :target: http://github.com/concordusapps/pytest-bench + `pytest-benchmark `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-benchmark-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-benchmark-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test fixture for benchmarking code + :target: http://plugincompat.herokuapp.com/output/pytest-benchmark-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-benchmark-latest?py=py34&pytest=2.7.0 :target: https://github.com/ionelmc/pytest-benchmark + `pytest-blockage `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-blockage-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-blockage-latest?py=py34&pytest=2.7.0 .. image:: github.png Disable network requests during a test run. + :target: http://plugincompat.herokuapp.com/output/pytest-blockage-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-blockage-latest?py=py34&pytest=2.7.0 :target: https://github.com/rob-b/pytest-blockage + `pytest-bpdb `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bpdb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bpdb-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plug-in to enable drop to bpdb debugger on test failure. + :target: http://plugincompat.herokuapp.com/output/pytest-bpdb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bpdb-latest?py=py34&pytest=2.7.0 :target: https://github.com/slafs/pytest-bpdb + `pytest-browsermob-proxy `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py34&pytest=2.7.0 .. image:: github.png BrowserMob proxy plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py34&pytest=2.7.0 :target: https://github.com/davehunt/pytest-browsermob-proxy + `pytest-bugzilla `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test bugzilla integration plugin + :target: http://plugincompat.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.7.0 :target: http://github.com/nibrahim/pytest_bugzilla + `pytest-cache `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs + :target: http://plugincompat.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-cache/ + `pytest-cagoule `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cagoule-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cagoule-latest?py=py34&pytest=2.7.0 .. image:: github.png Pytest plugin to only run tests affected by changes + :target: http://plugincompat.herokuapp.com/output/pytest-cagoule-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cagoule-latest?py=py34&pytest=2.7.0 :target: https://github.com/davidszotten/pytest-cagoule + `pytest-capturelog `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to capture log messages + :target: http://plugincompat.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/memedough/pytest-capturelog/overview + `pytest-catchlog `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-catchlog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-catchlog-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to catch log messages. This is a fork of pytest-capturelog. + :target: http://plugincompat.herokuapp.com/output/pytest-catchlog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-catchlog-latest?py=py34&pytest=2.7.0 :target: https://github.com/eisensheng/pytest-catchlog + `pytest-circleci `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-circleci-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-circleci-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for CircleCI + :target: http://plugincompat.herokuapp.com/output/pytest-circleci-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-circleci-latest?py=py34&pytest=2.7.0 :target: https://github.com/micktwomey/pytest-circleci + `pytest-cloud `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cloud-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cloud-latest?py=py34&pytest=2.7.0 .. image:: github.png Distributed tests planner plugin for pytest testing framework. + :target: http://plugincompat.herokuapp.com/output/pytest-cloud-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cloud-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-cloud + `pytest-codecheckers `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends) + :target: http://plugincompat.herokuapp.com/output/pytest-codecheckers-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-codecheckers-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-codecheckers/ + `pytest-colordots `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-colordots-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-colordots-latest?py=py34&pytest=2.7.0 .. image:: github.png Colorizes the progress indicators + :target: http://plugincompat.herokuapp.com/output/pytest-colordots-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-colordots-latest?py=py34&pytest=2.7.0 :target: https://github.com/svenstaro/pytest-colordots + `pytest-config `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-config-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-config-latest?py=py34&pytest=2.7.0 .. image:: github.png Base configurations and utilities for developing your Python project test suite with pytest. + :target: http://plugincompat.herokuapp.com/output/pytest-config-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-config-latest?py=py34&pytest=2.7.0 :target: https://github.com/buzzfeed/pytest_config + `pytest-contextfixture `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-contextfixture-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-contextfixture-latest?py=py34&pytest=2.7.0 .. image:: github.png Define pytest fixtures as context managers. + :target: http://plugincompat.herokuapp.com/output/pytest-contextfixture-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-contextfixture-latest?py=py34&pytest=2.7.0 :target: http://github.com/pelme/pytest-contextfixture/ + `pytest-couchdbkit `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-couchdbkit-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-couchdbkit-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test extension for per-test couchdb databases using couchdbkit + :target: http://plugincompat.herokuapp.com/output/pytest-couchdbkit-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-couchdbkit-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-couchdbkit + `pytest-cov `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cov-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cov-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing + :target: http://plugincompat.herokuapp.com/output/pytest-cov-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cov-latest?py=py34&pytest=2.7.0 :target: https://github.com/schlamar/pytest-cov + `pytest-cpp `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cpp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cpp-latest?py=py34&pytest=2.7.0 .. image:: github.png Use pytest's runner to discover and execute C++ tests + :target: http://plugincompat.herokuapp.com/output/pytest-cpp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cpp-latest?py=py34&pytest=2.7.0 :target: http://github.com/pytest-dev/pytest-cpp + `pytest-dbfixtures `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-dbfixtures-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-dbfixtures-latest?py=py34&pytest=2.7.0 .. image:: github.png Databases fixtures plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-dbfixtures-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-dbfixtures-latest?py=py34&pytest=2.7.0 :target: https://github.com/ClearcodeHQ/pytest-dbfixtures + `pytest-dbus-notification `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-dbus-notification-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-dbus-notification-latest?py=py34&pytest=2.7.0 .. image:: github.png D-BUS notifications for pytest results. + :target: http://plugincompat.herokuapp.com/output/pytest-dbus-notification-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-dbus-notification-latest?py=py34&pytest=2.7.0 :target: https://github.com/bmathieu33/pytest-dbus-notification + `pytest-describe `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-describe-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-describe-latest?py=py34&pytest=2.7.0 .. image:: github.png Describe-style plugin for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-describe-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-describe-latest?py=py34&pytest=2.7.0 :target: https://github.com/ropez/pytest-describe + `pytest-diffeo `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-diffeo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-diffeo-latest?py=py34&pytest=2.7.0 .. image:: github.png Common py.test support for Diffeo packages + :target: http://plugincompat.herokuapp.com/output/pytest-diffeo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-diffeo-latest?py=py34&pytest=2.7.0 :target: https://github.com/diffeo/pytest-diffeo + `pytest-django `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-latest?py=py34&pytest=2.7.0 `link `_ A Django plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-django-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-latest?py=py34&pytest=2.7.0 + `pytest-django-haystack `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-haystack-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-haystack-latest?py=py34&pytest=2.7.0 .. image:: github.png Cleanup your Haystack indexes between tests + :target: http://plugincompat.herokuapp.com/output/pytest-django-haystack-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-haystack-latest?py=py34&pytest=2.7.0 :target: http://github.com/rouge8/pytest-django-haystack + `pytest-django-lite `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-lite-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-lite-latest?py=py34&pytest=2.7.0 .. image:: github.png The bare minimum to integrate py.test with Django. + :target: http://plugincompat.herokuapp.com/output/pytest-django-lite-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-lite-latest?py=py34&pytest=2.7.0 :target: https://github.com/dcramer/pytest-django-lite + `pytest-django-sqlcount `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-sqlcount-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-sqlcount-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for reporting the number of SQLs executed per django testcase. + :target: http://plugincompat.herokuapp.com/output/pytest-django-sqlcount-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-sqlcount-latest?py=py34&pytest=2.7.0 :target: https://github.com/stj/pytest-django-sqlcount + `pytest-echo `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-echo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-echo-latest?py=py34&pytest=2.7.0 `link `_ pytest plugin with mechanisms for echoing environment variables, package version and generic attributes + :target: http://plugincompat.herokuapp.com/output/pytest-echo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-echo-latest?py=py34&pytest=2.7.0 + `pytest-env `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-env-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-env-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin that allows you to add environment variables. + :target: http://plugincompat.herokuapp.com/output/pytest-env-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-env-latest?py=py34&pytest=2.7.0 :target: https://github.com/MobileDynasty/pytest-env + `pytest-eradicate `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to check for commented out code + :target: http://plugincompat.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.7.0 :target: https://github.com/spil-johan/pytest-eradicate + `pytest-figleaf `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test figleaf coverage plugin + :target: http://plugincompat.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-figleaf + `pytest-fixture-tools `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.7.0 ? Plugin for pytest which provides tools for fixtures + :target: http://plugincompat.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.7.0 + `pytest-flakes `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to check source code with pyflakes + :target: http://plugincompat.herokuapp.com/output/pytest-flakes-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-flakes-latest?py=py34&pytest=2.7.0 :target: https://github.com/fschulze/pytest-flakes + `pytest-flask `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-flask-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-flask-latest?py=py34&pytest=2.7.0 .. image:: github.png A set of py.test fixtures to test Flask applications. + :target: http://plugincompat.herokuapp.com/output/pytest-flask-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-flask-latest?py=py34&pytest=2.7.0 :target: https://github.com/vitalk/pytest-flask + `pytest-greendots `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-greendots-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-greendots-latest?py=py34&pytest=2.7.0 ? Green progress dots + :target: http://plugincompat.herokuapp.com/output/pytest-greendots-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-greendots-latest?py=py34&pytest=2.7.0 + `pytest-growl `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-growl-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-growl-latest?py=py34&pytest=2.7.0 ? Growl notifications for pytest results. + :target: http://plugincompat.herokuapp.com/output/pytest-growl-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-growl-latest?py=py34&pytest=2.7.0 + `pytest-httpbin `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-httpbin-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-httpbin-latest?py=py34&pytest=2.7.0 .. image:: github.png Easily test your HTTP library against a local copy of httpbin + :target: http://plugincompat.herokuapp.com/output/pytest-httpbin-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-httpbin-latest?py=py34&pytest=2.7.0 :target: https://github.com/kevin1024/pytest-httpbin + `pytest-httpretty `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-httpretty-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-httpretty-latest?py=py34&pytest=2.7.0 .. image:: github.png A thin wrapper of HTTPretty for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-httpretty-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-httpretty-latest?py=py34&pytest=2.7.0 :target: http://github.com/papaeye/pytest-httpretty + `pytest-incremental `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-incremental-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-incremental-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png an incremental test runner (pytest plugin) + :target: http://plugincompat.herokuapp.com/output/pytest-incremental-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-incremental-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/schettino72/pytest-incremental + `pytest-instafail `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-instafail-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-instafail-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to show failures instantly + :target: http://plugincompat.herokuapp.com/output/pytest-instafail-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-instafail-latest?py=py34&pytest=2.7.0 :target: https://github.com/jpvanhal/pytest-instafail + `pytest-ipdb `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ipdb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ipdb-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plug-in to enable drop to ipdb debugger on test failure. + :target: http://plugincompat.herokuapp.com/output/pytest-ipdb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ipdb-latest?py=py34&pytest=2.7.0 :target: https://github.com/mverteuil/pytest-ipdb + `pytest-ipynb `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ipynb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ipynb-latest?py=py34&pytest=2.7.0 .. image:: github.png Use pytest's runner to discover and execute tests as cells of IPython notebooks + :target: http://plugincompat.herokuapp.com/output/pytest-ipynb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ipynb-latest?py=py34&pytest=2.7.0 :target: http://github.com/zonca/pytest-ipynb + `pytest-jira `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-jira-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-jira-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test JIRA integration plugin, using markers + :target: http://plugincompat.herokuapp.com/output/pytest-jira-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-jira-latest?py=py34&pytest=2.7.0 :target: http://github.com/jlaska/pytest_jira + `pytest-knows `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-knows-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-knows-latest?py=py34&pytest=2.7.0 .. image:: github.png A pytest plugin that can automaticly skip test case based on dependence info calculated by trace + :target: http://plugincompat.herokuapp.com/output/pytest-knows-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-knows-latest?py=py34&pytest=2.7.0 :target: https://github.com/mapix/ptknows + `pytest-konira `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-konira-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-konira-latest?py=py34&pytest=2.7.0 .. image:: github.png Run Konira DSL tests with py.test + :target: http://plugincompat.herokuapp.com/output/pytest-konira-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-konira-latest?py=py34&pytest=2.7.0 :target: http://github.com/alfredodeza/pytest-konira + `pytest-localserver `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-localserver-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-localserver-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to test server connections locally. + :target: http://plugincompat.herokuapp.com/output/pytest-localserver-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-localserver-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/basti/pytest-localserver/ + `pytest-marker-bugzilla `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test bugzilla integration plugin, using markers + :target: http://plugincompat.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py34&pytest=2.7.0 :target: http://github.com/eanxgeek/pytest_marker_bugzilla + `pytest-markfiltration `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-markfiltration-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-markfiltration-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN + :target: http://plugincompat.herokuapp.com/output/pytest-markfiltration-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-markfiltration-latest?py=py34&pytest=2.7.0 :target: https://github.com/adamgoucher/pytest-markfiltration + `pytest-marks `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-marks-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-marks-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN + :target: http://plugincompat.herokuapp.com/output/pytest-marks-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-marks-latest?py=py34&pytest=2.7.0 :target: https://github.com/adamgoucher/pytest-marks + `pytest-mock `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-mock-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-mock-latest?py=py34&pytest=2.7.0 .. image:: github.png Thin-wrapper around the mock package for easier use with py.test + :target: http://plugincompat.herokuapp.com/output/pytest-mock-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-mock-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-mock/ + `pytest-monkeyplus `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-monkeyplus-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-monkeyplus-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest's monkeypatch subclass with extra functionalities + :target: http://plugincompat.herokuapp.com/output/pytest-monkeyplus-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-monkeyplus-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hsoft/pytest-monkeyplus/ + `pytest-mozwebqa `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-mozwebqa-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-mozwebqa-latest?py=py34&pytest=2.7.0 .. image:: github.png Mozilla WebQA plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-mozwebqa-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-mozwebqa-latest?py=py34&pytest=2.7.0 :target: https://github.com/mozilla/pytest-mozwebqa + `pytest-multihost `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-multihost-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-multihost-latest?py=py34&pytest=2.7.0 `link `_ Utility for writing multi-host tests for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-multihost-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-multihost-latest?py=py34&pytest=2.7.0 + `pytest-oerp `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-oerp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-oerp-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to test OpenERP modules + :target: http://plugincompat.herokuapp.com/output/pytest-oerp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-oerp-latest?py=py34&pytest=2.7.0 :target: http://github.com/santagada/pytest-oerp/ + `pytest-oot `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-oot-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-oot-latest?py=py34&pytest=2.7.0 `link `_ Run object-oriented tests in a simple format + :target: http://plugincompat.herokuapp.com/output/pytest-oot-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-oot-latest?py=py34&pytest=2.7.0 + `pytest-optional `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-optional-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-optional-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png include/exclude values of fixtures in pytest + :target: http://plugincompat.herokuapp.com/output/pytest-optional-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-optional-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/maho/pytest-optional + `pytest-ordering `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ordering-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ordering-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to run your tests in a specific order + :target: http://plugincompat.herokuapp.com/output/pytest-ordering-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ordering-latest?py=py34&pytest=2.7.0 :target: https://github.com/ftobia/pytest-ordering + `pytest-osxnotify `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-osxnotify-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-osxnotify-latest?py=py34&pytest=2.7.0 .. image:: github.png OS X notifications for py.test results. + :target: http://plugincompat.herokuapp.com/output/pytest-osxnotify-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-osxnotify-latest?py=py34&pytest=2.7.0 :target: https://github.com/dbader/pytest-osxnotify + `pytest-paste-config `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.7.0 ? Allow setting the path to a paste config file + :target: http://plugincompat.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.7.0 + `pytest-pep257 `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pep257-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pep257-latest?py=py34&pytest=2.7.0 ? py.test plugin for pep257 + :target: http://plugincompat.herokuapp.com/output/pytest-pep257-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pep257-latest?py=py34&pytest=2.7.0 + `pytest-pep8 `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to check PEP8 requirements + :target: http://plugincompat.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-pep8/ + `pytest-pipeline `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.7.0 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines + :target: http://plugincompat.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.7.0 :target: https://github.com/bow/pytest_pipeline + `pytest-poo `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.7.0 .. image:: github.png Visualize your crappy tests + :target: http://plugincompat.herokuapp.com/output/pytest-poo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-poo-latest?py=py34&pytest=2.7.0 :target: http://github.com/pelme/pytest-poo + `pytest-poo-fail `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-fail-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-fail-latest?py=py34&pytest=2.7.0 .. image:: github.png Visualize your failed tests with poo + :target: http://plugincompat.herokuapp.com/output/pytest-poo-fail-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-poo-fail-latest?py=py34&pytest=2.7.0 :target: http://github.com/alyssa.barela/pytest-poo-fail + `pytest-pycharm `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pycharm-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pycharm-latest?py=py34&pytest=2.7.0 .. image:: github.png Plugin for py.test to enter PyCharm debugger on uncaught exceptions + :target: http://plugincompat.herokuapp.com/output/pytest-pycharm-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pycharm-latest?py=py34&pytest=2.7.0 :target: https://github.com/jlubcke/pytest-pycharm + `pytest-pydev `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pydev-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pydev-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to connect to a remote debug server with PyDev or PyCharm. + :target: http://plugincompat.herokuapp.com/output/pytest-pydev-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pydev-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/basti/pytest-pydev/ + `pytest-pyq `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pyq-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pyq-latest?py=py34&pytest=2.7.0 `link `_ Pytest fixture "q" for pyq + :target: http://plugincompat.herokuapp.com/output/pytest-pyq-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pyq-latest?py=py34&pytest=2.7.0 + `pytest-pythonpath `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pythonpath-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pythonpath-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin for adding to the PYTHONPATH from command line or configs. + :target: http://plugincompat.herokuapp.com/output/pytest-pythonpath-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pythonpath-latest?py=py34&pytest=2.7.0 :target: https://github.com/bigsassy/pytest-pythonpath + `pytest-qt `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-qt-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-qt-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest support for PyQt and PySide applications + :target: http://plugincompat.herokuapp.com/output/pytest-qt-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-qt-latest?py=py34&pytest=2.7.0 :target: http://github.com/pytest-dev/pytest-qt + `pytest-quickcheck `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-quickcheck-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-quickcheck-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to generate random data inspired by QuickCheck + :target: http://plugincompat.herokuapp.com/output/pytest-quickcheck-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-quickcheck-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/t2y/pytest-quickcheck/ + `pytest-rage `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-rage-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-rage-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to implement PEP712 + :target: http://plugincompat.herokuapp.com/output/pytest-rage-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-rage-latest?py=py34&pytest=2.7.0 :target: http://github.com/santagada/pytest-rage/ + `pytest-raisesregexp `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-raisesregexp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-raisesregexp-latest?py=py34&pytest=2.7.0 .. image:: github.png Simple pytest plugin to look for regex in Exceptions + :target: http://plugincompat.herokuapp.com/output/pytest-raisesregexp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-raisesregexp-latest?py=py34&pytest=2.7.0 :target: https://github.com/Walkman/pytest_raisesregexp + `pytest-random `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-random-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-random-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to randomize tests + :target: http://plugincompat.herokuapp.com/output/pytest-random-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-random-latest?py=py34&pytest=2.7.0 :target: https://github.com/klrmn/pytest-random + `pytest-readme `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-readme-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-readme-latest?py=py34&pytest=2.7.0 .. image:: github.png Test your README.md file + :target: http://plugincompat.herokuapp.com/output/pytest-readme-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-readme-latest?py=py34&pytest=2.7.0 :target: https://github.com/boxed/pytest-readme + `pytest-regtest `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-regtest-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-regtest-latest?py=py34&pytest=2.7.0 `link `_ py.test plugin for regression tests + :target: http://plugincompat.herokuapp.com/output/pytest-regtest-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-regtest-latest?py=py34&pytest=2.7.0 + `pytest-remove-stale-bytecode `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-remove-stale-bytecode-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-remove-stale-bytecode-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to remove stale byte code files. + :target: http://plugincompat.herokuapp.com/output/pytest-remove-stale-bytecode-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-remove-stale-bytecode-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/gocept/pytest-remove-stale-bytecode/ + `pytest-rerunfailures `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-rerunfailures-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-rerunfailures-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to re-run tests to eliminate flakey failures + :target: http://plugincompat.herokuapp.com/output/pytest-rerunfailures-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-rerunfailures-latest?py=py34&pytest=2.7.0 :target: https://github.com/klrmn/pytest-rerunfailures + `pytest-runfailed `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-runfailed-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-runfailed-latest?py=py34&pytest=2.7.0 .. image:: github.png implement a --failed option for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-runfailed-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-runfailed-latest?py=py34&pytest=2.7.0 :target: http://github.com/dmerejkowsky/pytest-runfailed + `pytest-runner `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-runner-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-runner-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png Invoke py.test as distutils command with dependency resolution. + :target: http://plugincompat.herokuapp.com/output/pytest-runner-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-runner-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/jaraco/pytest-runner + `pytest-services `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-services-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-services-latest?py=py34&pytest=2.7.0 .. image:: github.png Services plugin for pytest testing framework + :target: http://plugincompat.herokuapp.com/output/pytest-services-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-services-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-services + `pytest-sftpserver `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sftpserver-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sftpserver-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to locally test sftp server connections. + :target: http://plugincompat.herokuapp.com/output/pytest-sftpserver-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sftpserver-latest?py=py34&pytest=2.7.0 :target: http://github.com/ulope/pytest-sftpserver/ + `pytest-smartcov `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-smartcov-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-smartcov-latest?py=py34&pytest=2.7.0 .. image:: github.png Smart coverage plugin for pytest. + :target: http://plugincompat.herokuapp.com/output/pytest-smartcov-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-smartcov-latest?py=py34&pytest=2.7.0 :target: https://github.com/carljm/pytest-smartcov/ + `pytest-sourceorder `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sourceorder-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sourceorder-latest?py=py34&pytest=2.7.0 `link `_ Test-ordering plugin for pytest + :target: http://plugincompat.herokuapp.com/output/pytest-sourceorder-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sourceorder-latest?py=py34&pytest=2.7.0 + `pytest-spec `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-spec-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-spec-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to display test execution output like a SPECIFICATION + :target: http://plugincompat.herokuapp.com/output/pytest-spec-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-spec-latest?py=py34&pytest=2.7.0 :target: https://github.com/pchomik/pytest-spec + `pytest-splinter `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-splinter-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-splinter-latest?py=py34&pytest=2.7.0 .. image:: github.png Splinter plugin for pytest testing framework + :target: http://plugincompat.herokuapp.com/output/pytest-splinter-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-splinter-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-splinter + `pytest-stepwise `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-stepwise-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-stepwise-latest?py=py34&pytest=2.7.0 .. image:: github.png Run a test suite one failing test at a time. + :target: http://plugincompat.herokuapp.com/output/pytest-stepwise-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-stepwise-latest?py=py34&pytest=2.7.0 :target: https://github.com/nip3o/pytest-stepwise + `pytest-sugar `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sugar-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sugar-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test is a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly). + :target: http://plugincompat.herokuapp.com/output/pytest-sugar-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sugar-latest?py=py34&pytest=2.7.0 :target: https://github.com/Frozenball/pytest-sugar + `pytest-timeout `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-timeout-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-timeout-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to abort hanging tests + :target: http://plugincompat.herokuapp.com/output/pytest-timeout-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-timeout-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/flub/pytest-timeout/ + `pytest-tornado `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-tornado-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-tornado-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. + :target: http://plugincompat.herokuapp.com/output/pytest-tornado-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-tornado-latest?py=py34&pytest=2.7.0 :target: https://github.com/eugeniy/pytest-tornado + `pytest-translations `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-translations-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-translations-latest?py=py34&pytest=2.7.0 .. image:: github.png Test your translation files + :target: http://plugincompat.herokuapp.com/output/pytest-translations-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-translations-latest?py=py34&pytest=2.7.0 :target: https://github.com/thermondo/pytest-translations + `pytest-twisted `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.7.0 .. image:: github.png A twisted plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.7.0 :target: https://github.com/schmir/pytest-twisted + `pytest-unmarked `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-unmarked-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-unmarked-latest?py=py34&pytest=2.7.0 .. image:: github.png Run only unmarked tests + :target: http://plugincompat.herokuapp.com/output/pytest-unmarked-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-unmarked-latest?py=py34&pytest=2.7.0 :target: http://github.com/alyssa.barela/pytest-unmarked + `pytest-watch `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-watch-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-watch-latest?py=py34&pytest=2.7.0 .. image:: github.png Local continuous test runner with pytest and watchdog. + :target: http://plugincompat.herokuapp.com/output/pytest-watch-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-watch-latest?py=py34&pytest=2.7.0 :target: http://github.com/joeyespo/pytest-watch + `pytest-xdist `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes + :target: http://plugincompat.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-xdist + `pytest-xprocess `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to manage external processes across test runs + :target: http://plugincompat.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-xprocess/ + `pytest-yamlwsgi `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.7.0 ? Run tests against wsgi apps defined in yaml + :target: http://plugincompat.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.7.0 + `pytest-zap `_ .. image:: http://plugincompat.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.7.0 .. image:: github.png OWASP ZAP plugin for py.test. + :target: http://plugincompat.herokuapp.com/output/pytest-zap-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-zap-latest?py=py34&pytest=2.7.0 :target: https://github.com/davehunt/pytest-zap -==================================================================================== ================================================================================================================= ================================================================================================================= =========================================================================== ============================================================================================================================================= +============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== ============================================================================================================================================= -*(Updated on 2014-09-27)* +*(Updated on 2015-02-28)* diff -r c3dd3f237dd4cf8cbfa61ce1522f979f77d6e7b7 -r 163964f4f0f48204f9f42d080778f23d6673f0b0 doc/en/plugins_index/plugins_index.py --- a/doc/en/plugins_index/plugins_index.py +++ b/doc/en/plugins_index/plugins_index.py @@ -10,7 +10,7 @@ versions from PyPI. Also includes plugin compatibility between different python and pytest versions, -obtained from http://pytest-plugs.herokuapp.com. +obtained from http://plugincompat.herokuapp.com. """ from __future__ import print_function from collections import namedtuple @@ -61,7 +61,7 @@ yield name, str(loose_version) -def obtain_plugins_table(plugins, client, verbose): +def obtain_plugins_table(plugins, client, verbose, pytest_ver): """ Returns information to populate a table of plugins, their versions, authors, etc. @@ -73,7 +73,11 @@ :param plugins: list of (name, version) :param client: ServerProxy :param verbose: print plugin name and version as they are fetch + :param pytest_ver: pytest version to use. """ + if pytest_ver is None: + pytest_ver = pytest.__version__ + def get_repo_markup(repo): """ obtains appropriate markup for the given repository, as two lines @@ -107,9 +111,8 @@ rows = [] ColumnData = namedtuple('ColumnData', 'text link') headers = ['Name', 'Py27', 'Py34', 'Home', 'Summary'] - pytest_version = pytest.__version__ repositories = obtain_override_repositories() - print('Generating plugins_index page (pytest-{0})'.format(pytest_version)) + print('Generating plugins_index page (pytest-{0})'.format(pytest_ver)) plugins = list(plugins) for index, (package_name, version) in enumerate(plugins): if verbose: @@ -118,7 +121,7 @@ release_data = client.release_data(package_name, version) common_params = dict( - site='http://pytest-plugs.herokuapp.com', + site='http://plugincompat.herokuapp.com', name=package_name, version=version) @@ -131,9 +134,9 @@ image_url += '?py={py}&pytest={pytest}' row = ( ColumnData(package_name, release_data['package_url']), - ColumnData(image_url.format(py='py27', pytest=pytest_version), + ColumnData(image_url.format(py='py27', pytest=pytest_ver), None), - ColumnData(image_url.format(py='py34', pytest=pytest_version), + ColumnData(image_url.format(py='py34', pytest=pytest_ver), None), ColumnData( repo_markup_1, @@ -150,9 +153,9 @@ row = ( ColumnData('', None), - ColumnData(output_url.format(py='py27', pytest=pytest_version), + ColumnData(output_url.format(py='py27', pytest=pytest_ver), None), - ColumnData(output_url.format(py='py34', pytest=pytest_version), + ColumnData(output_url.format(py='py34', pytest=pytest_ver), None), ColumnData(repo_markup_2, None), ColumnData('', None), @@ -184,13 +187,14 @@ } -def generate_plugins_index_from_table(filename, headers, rows): +def generate_plugins_index_from_table(filename, headers, rows, pytest_ver): """ Generates a RST file with the table data given. :param filename: output filename :param headers: see `obtain_plugins_table` :param rows: see `obtain_plugins_table` + :param pytest_ver: see `obtain_plugins_table` """ # creates a list of rows, each being a str containing appropriate column # text and link @@ -215,7 +219,7 @@ with open(filename, 'w') as f: # header - header_text = HEADER.format(pytest_version=pytest.__version__) + header_text = HEADER.format(pytest_version=pytest_ver) print(header_text, file=f) print(file=f) @@ -240,7 +244,7 @@ print('*(Updated on %s)*' % today, file=f) -def generate_plugins_index(client, filename, verbose): +def generate_plugins_index(client, filename, verbose, pytest_ver): """ Generates an RST file with a table of the latest pytest plugins found in PyPI. @@ -248,10 +252,12 @@ :param client: ServerProxy :param filename: output filename :param verbose: print name and version of each plugin as they are fetch + :param pytest_ver: pytest version to use; if not given, use current pytest + version. """ plugins = get_latest_versions(iter_plugins(client)) - headers, rows = obtain_plugins_table(plugins, client, verbose) - generate_plugins_index_from_table(filename, headers, rows) + headers, rows = obtain_plugins_table(plugins, client, verbose, pytest_ver) + generate_plugins_index_from_table(filename, headers, rows, pytest_ver) def main(argv): @@ -270,10 +276,12 @@ help='url of PyPI server to obtain data from [default: %default]') parser.add_option('-v', '--verbose', default=False, action='store_true', help='verbose output') + parser.add_option('--pytest-ver', default=None, action='store', + help='generate index for this pytest version (default current version)') (options, _) = parser.parse_args(argv[1:]) client = get_proxy(options.url) - generate_plugins_index(client, options.filename, options.verbose) + generate_plugins_index(client, options.filename, options.verbose, options.pytest_ver) print() print('%s updated.' % options.filename) @@ -291,7 +299,7 @@ 3.3. A complete listing can also be found at -`pytest-plugs `_, which contains tests +`plugincompat `_, which contains tests status against other py.test releases. ''' Repository URL: https://bitbucket.org/pytest-dev/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. From builds at drone.io Sat Feb 28 21:50:21 2015 From: builds at drone.io (Drone.io Build) Date: Sat, 28 Feb 2015 20:50:21 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 13 Message-ID: <20150228205020.19154.16752@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest/13 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 3892:ebe73a63994f Author : Anatoly Bubenkov Branch : plugincompat-move Message: Close branch plugincompat-move -------------- next part -------------- An HTML attachment was scrubbed... URL: From builds at drone.io Sat Feb 28 22:02:15 2015 From: builds at drone.io (Drone.io Build) Date: Sat, 28 Feb 2015 21:02:15 +0000 Subject: [Pytest-commit] [SUCCESS] pytest - # 14 Message-ID: <20150228210215.15320.13371@drone.io> Build was Successful Build : https://drone.io/bitbucket.org/pytest-dev/pytest/14 Project : https://drone.io/bitbucket.org/pytest-dev/pytest Repository : https://bitbucket.org/pytest-dev/pytest Version : 4029:163964f4f0f4 Author : Anatoly Bubenkov Branch : default Message: Merged in plugincompat-move (pull request #256) -------------- next part -------------- An HTML attachment was scrubbed... URL: