Merge pull request #1705 from RonnyPfannschmidt/merge-master
Merge from master to features
This commit is contained in:
		
						commit
						293351cfd0
					
				|  | @ -172,13 +172,36 @@ | |||
| * Add proposal to docs for a new feature that enables users to combine multiple | ||||
|   fixtures into one. Thanks to `@hpk42`_ and `@hackebrot`_. | ||||
| 
 | ||||
| * Rename ``getfuncargvalue`` to ``getfixturevalue``. ``getfuncargvalue`` is | ||||
|   deprecated but still present. Thanks to `@RedBeardCode`_ and `@tomviner`_ | ||||
|   for PR (`#1626`_). | ||||
| 
 | ||||
| * Always include full assertion explanation. The previous behaviour was hiding | ||||
|   sub-expressions that happened to be False, assuming this was redundant information. | ||||
|   Thanks `@bagerard`_ for reporting (`#1503`_). Thanks to `@davehunt`_ and | ||||
|   `@tomviner`_ for PR. | ||||
| 
 | ||||
| * Renamed the pytest ``pdb`` module (plugin) into ``debugging``. | ||||
| 
 | ||||
| * Improve of the test output for logical expression with brackets. | ||||
|   Fixes(`#925`_). Thanks `@DRMacIver`_ for reporting. Thanks to `@RedBeardCode`_ | ||||
|   for PR. | ||||
| 
 | ||||
| * ImportErrors in plugins now are a fatal error instead of issuing a | ||||
| 
 | ||||
| .. _#1632: https://github.com/pytest-dev/pytest/issues/1632 | ||||
| 
 | ||||
|   pytest warning (`#1479`_). Thanks to `@The-Compiler`_ for the PR. | ||||
| 
 | ||||
| .. _#1580: https://github.com/pytest-dev/pytest/pull/1580 | ||||
| .. _#1605: https://github.com/pytest-dev/pytest/issues/1605 | ||||
| .. _#1597: https://github.com/pytest-dev/pytest/pull/1597 | ||||
| .. _#460: https://github.com/pytest-dev/pytest/pull/460 | ||||
| .. _#1553: https://github.com/pytest-dev/pytest/issues/1553 | ||||
| .. _#1626: https://github.com/pytest-dev/pytest/pull/1626 | ||||
| .. _#1503: https://github.com/pytest-dev/pytest/issues/1503 | ||||
| .. _#1479: https://github.com/pytest-dev/pytest/issues/1479 | ||||
| .. _#925: https://github.com/pytest-dev/pytest/issues/925 | ||||
| 
 | ||||
| .. _@graingert: https://github.com/graingert | ||||
| .. _@taschini: https://github.com/taschini | ||||
|  | @ -187,6 +210,8 @@ | |||
| .. _@Vogtinator: https://github.com/Vogtinator | ||||
| .. _@blueyed: https://github.com/blueyed | ||||
| .. _@fengxx: https://github.com/fengxx | ||||
| .. _@bagerard: https://github.com/bagerard | ||||
| .. _@DRMacIver: https://github.com/DRMacIver | ||||
| 
 | ||||
| * Fix `#1421`_: Exit tests if a collection error occurs and add | ||||
|   ``--continue-on-collection-errors`` option to restore previous behaviour. | ||||
|  |  | |||
|  | @ -120,6 +120,8 @@ the following: | |||
| 
 | ||||
| - an issue tracker for bug reports and enhancement requests. | ||||
| 
 | ||||
| - a `changelog <http://keepachangelog.com/>`_ | ||||
| 
 | ||||
| If no contributor strongly objects and two agree, the repository can then be | ||||
| transferred to the ``pytest-dev`` organisation. | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| """Rewrite assertion AST to produce nice error messages""" | ||||
| 
 | ||||
| import ast | ||||
| import _ast | ||||
| import errno | ||||
| import itertools | ||||
| import imp | ||||
|  | @ -876,6 +877,8 @@ class AssertionRewriter(ast.NodeVisitor): | |||
|     def visit_Compare(self, comp): | ||||
|         self.push_format_context() | ||||
|         left_res, left_expl = self.visit(comp.left) | ||||
|         if isinstance(comp.left, (_ast.Compare, _ast.BoolOp)): | ||||
|             left_expl = "({0})".format(left_expl) | ||||
|         res_variables = [self.variable() for i in range(len(comp.ops))] | ||||
|         load_names = [ast.Name(v, ast.Load()) for v in res_variables] | ||||
|         store_names = [ast.Name(v, ast.Store()) for v in res_variables] | ||||
|  | @ -885,6 +888,8 @@ class AssertionRewriter(ast.NodeVisitor): | |||
|         results = [left_res] | ||||
|         for i, op, next_operand in it: | ||||
|             next_res, next_expl = self.visit(next_operand) | ||||
|             if isinstance(next_operand, (_ast.Compare, _ast.BoolOp)): | ||||
|                 next_expl = "({0})".format(next_expl) | ||||
|             results.append(next_res) | ||||
|             sym = binop_map[op.__class__] | ||||
|             syms.append(ast.Str(sym)) | ||||
|  |  | |||
|  | @ -38,44 +38,11 @@ def format_explanation(explanation): | |||
|     displaying diffs. | ||||
|     """ | ||||
|     explanation = ecu(explanation) | ||||
|     explanation = _collapse_false(explanation) | ||||
|     lines = _split_explanation(explanation) | ||||
|     result = _format_lines(lines) | ||||
|     return u('\n').join(result) | ||||
| 
 | ||||
| 
 | ||||
| def _collapse_false(explanation): | ||||
|     """Collapse expansions of False | ||||
| 
 | ||||
|     So this strips out any "assert False\n{where False = ...\n}" | ||||
|     blocks. | ||||
|     """ | ||||
|     where = 0 | ||||
|     while True: | ||||
|         start = where = explanation.find("False\n{False = ", where) | ||||
|         if where == -1: | ||||
|             break | ||||
|         level = 0 | ||||
|         prev_c = explanation[start] | ||||
|         for i, c in enumerate(explanation[start:]): | ||||
|             if prev_c + c == "\n{": | ||||
|                 level += 1 | ||||
|             elif prev_c + c == "\n}": | ||||
|                 level -= 1 | ||||
|                 if not level: | ||||
|                     break | ||||
|             prev_c = c | ||||
|         else: | ||||
|             raise AssertionError("unbalanced braces: %r" % (explanation,)) | ||||
|         end = start + i | ||||
|         where = end | ||||
|         if explanation[end - 1] == '\n': | ||||
|             explanation = (explanation[:start] + explanation[start+15:end-1] + | ||||
|                            explanation[end+1:]) | ||||
|             where -= 17 | ||||
|     return explanation | ||||
| 
 | ||||
| 
 | ||||
| def _split_explanation(explanation): | ||||
|     """Return a list of individual lines in the explanation | ||||
| 
 | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ class UsageError(Exception): | |||
| _preinit = [] | ||||
| 
 | ||||
| default_plugins = ( | ||||
|      "mark main terminal runner python pdb unittest capture skipping " | ||||
|      "mark main terminal runner python debugging unittest capture skipping " | ||||
|      "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion " | ||||
|      "junitxml resultlog doctest cacheprovider freeze_support " | ||||
|      "setuponly setupplan").split() | ||||
|  | @ -656,20 +656,17 @@ class Argument: | |||
|                 self._long_opts.append(opt) | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         retval = 'Argument(' | ||||
|         args = [] | ||||
|         if self._short_opts: | ||||
|             retval += '_short_opts: ' + repr(self._short_opts) + ', ' | ||||
|             args += ['_short_opts: ' + repr(self._short_opts)] | ||||
|         if self._long_opts: | ||||
|             retval += '_long_opts: ' + repr(self._long_opts) + ', ' | ||||
|         retval += 'dest: ' + repr(self.dest) + ', ' | ||||
|             args += ['_long_opts: ' + repr(self._long_opts)] | ||||
|         args += ['dest: ' + repr(self.dest)] | ||||
|         if hasattr(self, 'type'): | ||||
|             retval += 'type: ' + repr(self.type) + ', ' | ||||
|             args += ['type: ' + repr(self.type)] | ||||
|         if hasattr(self, 'default'): | ||||
|             retval += 'default: ' + repr(self.default) + ', ' | ||||
|         if retval[-2:] == ', ':  # always long enough to test ("Argument(" ) | ||||
|             retval = retval[:-2] | ||||
|         retval += ')' | ||||
|         return retval | ||||
|             args += ['default: ' + repr(self.default)] | ||||
|         return 'Argument({0})'.format(', '.join(args)) | ||||
| 
 | ||||
| 
 | ||||
| class OptionGroup: | ||||
|  | @ -928,10 +925,7 @@ class Config(object): | |||
|             args[:] = self.getini("addopts") + args | ||||
|         self._checkversion() | ||||
|         self.pluginmanager.consider_preparse(args) | ||||
|         try: | ||||
|             self.pluginmanager.load_setuptools_entrypoints("pytest11") | ||||
|         except ImportError as e: | ||||
|             self.warn("I2", "could not load setuptools entry import: %s" % (e,)) | ||||
|         self.pluginmanager.load_setuptools_entrypoints("pytest11") | ||||
|         self.pluginmanager.consider_env() | ||||
|         self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy()) | ||||
|         if self.known_args_namespace.confcutdir is None and self.inifile: | ||||
|  |  | |||
|  | @ -70,7 +70,7 @@ class DoctestItem(pytest.Item): | |||
|     def setup(self): | ||||
|         if self.dtest is not None: | ||||
|             self.fixture_request = _setup_fixtures(self) | ||||
|             globs = dict(getfixture=self.fixture_request.getfuncargvalue) | ||||
|             globs = dict(getfixture=self.fixture_request.getfixturevalue) | ||||
|             for name, value in self.fixture_request.getfuncargvalue('doctest_namespace').items(): | ||||
|                 globs[name] = value | ||||
|             self.dtest.globs.update(globs) | ||||
|  |  | |||
|  | @ -6,8 +6,9 @@ import inspect | |||
| import re | ||||
| import types | ||||
| import sys | ||||
| import math | ||||
| import warnings | ||||
| import collections | ||||
| import math | ||||
| 
 | ||||
| import py | ||||
| import pytest | ||||
|  | @ -1855,7 +1856,7 @@ class FixtureRequest(FuncargnamesCompatAttr): | |||
|         fixturedefs = self._arg2fixturedefs.get(argname, None) | ||||
|         if fixturedefs is None: | ||||
|             # we arrive here because of a  a dynamic call to | ||||
|             # getfuncargvalue(argname) usage which was naturally | ||||
|             # getfixturevalue(argname) usage which was naturally | ||||
|             # not known at parsing/collection time | ||||
|             fixturedefs = self._fixturemanager.getfixturedefs( | ||||
|                             argname, self._pyfuncitem.parent.nodeid) | ||||
|  | @ -1950,7 +1951,7 @@ class FixtureRequest(FuncargnamesCompatAttr): | |||
|         fixturenames = getattr(item, "fixturenames", self.fixturenames) | ||||
|         for argname in fixturenames: | ||||
|             if argname not in item.funcargs: | ||||
|                 item.funcargs[argname] = self.getfuncargvalue(argname) | ||||
|                 item.funcargs[argname] = self.getfixturevalue(argname) | ||||
| 
 | ||||
|     def cached_setup(self, setup, teardown=None, scope="module", extrakey=None): | ||||
|         """ (deprecated) Return a testing resource managed by ``setup`` & | ||||
|  | @ -1984,17 +1985,23 @@ class FixtureRequest(FuncargnamesCompatAttr): | |||
|                 self._addfinalizer(finalizer, scope=scope) | ||||
|         return val | ||||
| 
 | ||||
|     def getfuncargvalue(self, argname): | ||||
|         """ Dynamically retrieve a named fixture function argument. | ||||
|     def getfixturevalue(self, argname): | ||||
|         """ Dynamically run a named fixture function. | ||||
| 
 | ||||
|         As of pytest-2.3, it is easier and usually better to access other | ||||
|         fixture values by stating it as an input argument in the fixture | ||||
|         function.  If you only can decide about using another fixture at test | ||||
|         Declaring fixtures via function argument is recommended where possible. | ||||
|         But if you can only decide whether to use another fixture at test | ||||
|         setup time, you may use this function to retrieve it inside a fixture | ||||
|         function body. | ||||
|         or test function body. | ||||
|         """ | ||||
|         return self._get_active_fixturedef(argname).cached_result[0] | ||||
| 
 | ||||
|     def getfuncargvalue(self, argname): | ||||
|         """ Deprecated, use getfixturevalue. """ | ||||
|         warnings.warn( | ||||
|             "use of getfuncargvalue is deprecated, use getfixturevalue", | ||||
|             DeprecationWarning) | ||||
|         return self.getfixturevalue(argname) | ||||
| 
 | ||||
|     def _get_active_fixturedef(self, argname): | ||||
|         try: | ||||
|             return self._fixturedefs[argname] | ||||
|  | @ -2010,7 +2017,7 @@ class FixtureRequest(FuncargnamesCompatAttr): | |||
|                 raise | ||||
|         # remove indent to prevent the python3 exception | ||||
|         # from leaking into the call | ||||
|         result = self._getfuncargvalue(fixturedef) | ||||
|         result = self._getfixturevalue(fixturedef) | ||||
|         self._funcargs[argname] = result | ||||
|         self._fixturedefs[argname] = fixturedef | ||||
|         return fixturedef | ||||
|  | @ -2026,7 +2033,7 @@ class FixtureRequest(FuncargnamesCompatAttr): | |||
|             l.append(fixturedef) | ||||
|             current = current._parent_request | ||||
| 
 | ||||
|     def _getfuncargvalue(self, fixturedef): | ||||
|     def _getfixturevalue(self, fixturedef): | ||||
|         # prepare a subrequest object before calling fixture function | ||||
|         # (latter managed by fixturedef) | ||||
|         argname = fixturedef.argname | ||||
|  |  | |||
|  | @ -5,6 +5,13 @@ environment: | |||
|     # using pytestbot account as detailed here: | ||||
|     # https://www.appveyor.com/docs/build-configuration#secure-variables | ||||
| 
 | ||||
|   matrix: | ||||
|   # create multiple jobs to execute a set of tox runs on each; this is to workaround having | ||||
|   # builds timing out in AppVeyor | ||||
|   - TOXENV: "linting,py26,py27,py33,py34,py35,pypy" | ||||
|   - TOXENV: "py27-pexpect,py27-xdist,py27-trial,py35-pexpect,py35-xdist,py35-trial" | ||||
|   - TOXENV: "py27-nobyte,doctesting,py27-cxfreeze" | ||||
| 
 | ||||
| install: | ||||
|   - echo Installed Pythons | ||||
|   - dir c:\Python* | ||||
|  |  | |||
|  | @ -1,19 +1,5 @@ | |||
| {% extends "!layout.html" %} | ||||
| {% block header %} | ||||
| <div align="center" xmlns="http://www.w3.org/1999/html" style="background-color: lightgreen;  padding: .5em"> | ||||
|   <h4> | ||||
|       Want to help improve pytest?  Please  | ||||
|     <a href="https://www.indiegogo.com/projects/python-testing-sprint-mid-2016#/"> | ||||
|         contribute to | ||||
|     </a> | ||||
|     or  | ||||
|     <a href="announce/sprint2016.html"> | ||||
|         join | ||||
|     </a> | ||||
|     our upcoming sprint in June 2016! | ||||
| 
 | ||||
|   </h4> | ||||
| </div> | ||||
|   {{super()}} | ||||
| {% endblock %} | ||||
| {% block footer %} | ||||
|  |  | |||
|  | @ -1,10 +1,5 @@ | |||
| <h3>Useful Links</h3> | ||||
| <ul> | ||||
|   <li> | ||||
|     <a href="https://www.indiegogo.com/projects/python-testing-sprint-mid-2016#/"> | ||||
|       <b>Sprint funding campaign</b> | ||||
|     </a> | ||||
|   </li> | ||||
|   <li><a href="{{ pathto('index') }}">The pytest Website</a></li> | ||||
|   <li><a href="{{ pathto('contributing') }}">Contribution Guide</a></li> | ||||
|   <li><a href="https://pypi.python.org/pypi/pytest">pytest @ PyPI</a></li> | ||||
|  |  | |||
|  | @ -4,9 +4,9 @@ python testing sprint June 20th-26th 2016 | |||
| .. image:: ../img/freiburg2.jpg | ||||
|    :width: 400 | ||||
| 
 | ||||
| The pytest core group is heading towards the biggest sprint | ||||
| in its history, to take place in the black forest town Freiburg | ||||
| in Germany.  As of February 2016 we have started a `funding | ||||
| The pytest core group held the biggest sprint | ||||
| in its history in June 2016, taking place in the black forest town Freiburg | ||||
| in Germany.  In February 2016 we started a `funding | ||||
| campaign on Indiegogo to cover expenses | ||||
| <http://igg.me/at/pytest-sprint/x/4034848>`_ The page also mentions | ||||
| some preliminary topics: | ||||
|  | @ -35,73 +35,32 @@ some preliminary topics: | |||
| Participants | ||||
| -------------- | ||||
| 
 | ||||
| Here are preliminary participants who said they are likely to come, | ||||
| given some expenses funding:: | ||||
| 
 | ||||
|     Anatoly Bubenkoff, Netherlands | ||||
| Over 20 participants took part from 4 continents, including employees | ||||
| from Splunk, Personalkollen, Cobe.io, FanDuel and Dolby. Some newcomers | ||||
| mixed with developers who have worked on pytest since its beginning, and | ||||
| of course everyone in between. | ||||
|     Ana Ribeiro, Brazil | ||||
|     Andreas Pelme, Personalkollen, Sweden | ||||
|     Anthony Wang, Splunk, US | ||||
|     Brianna Laugher, Australia | ||||
|     Bruno Oliveira, Brazil | ||||
|     Danielle Jenkins, Splunk, US | ||||
|     Dave Hunt, UK | ||||
|     Florian Bruhin, Switzerland | ||||
|     Floris Bruynooghe, Cobe.io, UK | ||||
|     Holger Krekel, merlinux, Germany | ||||
|     Oliver Bestwalter, Avira, Germany | ||||
|     Omar Kohl, Germany | ||||
|     Raphael Pierzina, FanDuel, UK | ||||
|     Ronny Pfannschmidt, Germany  | ||||
|     Tom Viner, UK | ||||
| 
 | ||||
|     <your name here?> | ||||
| 
 | ||||
| Other contributors and experienced newcomers are invited to join as well | ||||
| but please send a mail to the pytest-dev mailing list if you intend to | ||||
| do so somewhat soon, also how much funding you need if so.  And if you | ||||
| are working for a company and using pytest heavily you are welcome to | ||||
| join and we encourage your company to provide some funding for the | ||||
| sprint.  They may see it, and rightfully so, as a very cheap and deep | ||||
| training which brings you together with the experts in the field :) | ||||
| 
 | ||||
| 
 | ||||
| Sprint organisation, schedule | ||||
| ------------------------------- | ||||
| 
 | ||||
| tentative schedule: | ||||
| People arrived in Freiburg on the 19th, with sprint development taking | ||||
| place on 20th, 21st, 22nd, 24th and 25th. On the 23rd we took a break | ||||
| day for some hot hiking in the Black Forest. | ||||
| 
 | ||||
| - 19/20th arrival in Freiburg | ||||
| - 20th social get together, initial hacking | ||||
| - 21/22th full sprint days | ||||
| - 23rd break day, hiking | ||||
| - 24/25th full sprint days | ||||
| - 26th departure | ||||
| Sprint activity was organised heavily around pairing, with plenty of group | ||||
| discusssions to take advantage of the high bandwidth, and lightning talks | ||||
| as well. | ||||
| 
 | ||||
| We might adjust according to weather to make sure that if | ||||
| we do some hiking or excursion we'll have good weather. | ||||
| Freiburg is one of the sunniest places in Germany so | ||||
| it shouldn't be too much of a constraint. | ||||
| 
 | ||||
| 
 | ||||
| Accomodation | ||||
| ---------------- | ||||
| 
 | ||||
| We'll see to arrange for renting a flat with multiple | ||||
| beds/rooms.  Hotels are usually below 100 per night. | ||||
| The earlier we book the better. | ||||
| 
 | ||||
| Money / funding | ||||
| --------------- | ||||
| 
 | ||||
| The Indiegogo campaign asks for 11000 USD which should cover | ||||
| the costs for flights and accomodation, renting a sprint place | ||||
| and maybe a bit of food as well. | ||||
| 
 | ||||
| If your organisation wants to support the sprint but prefers | ||||
| to give money according to an invoice, get in contact with | ||||
| holger at http://merlinux.eu who can invoice your organisation | ||||
| properly. | ||||
| The Indiegogo campaign aimed for 11000 USD and in the end raised over | ||||
| 12000, to reimburse travel costs, pay for a sprint venue and catering. | ||||
| 
 | ||||
| If we have excess money we'll use for further sprint/travel | ||||
| funding for pytest/tox contributors. | ||||
| Excess money is reserved for further sprint/travel funding for pytest/tox | ||||
| contributors. | ||||
|  |  | |||
|  | @ -823,6 +823,10 @@ If we run it, we get two passing tests:: | |||
| 
 | ||||
| Here is how autouse fixtures work in other scopes: | ||||
| 
 | ||||
| - autouse fixtures obey the ``scope=`` keyword-argument: if an autouse fixture | ||||
|   has ``scope='session'`` it will only be run once, no matter where it is | ||||
|   defined. ``scope='class'`` means it will be run once per class, etc. | ||||
| 
 | ||||
| - if an autouse fixture is defined in a test module, all its test | ||||
|   functions automatically use it. | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ class Writer: | |||
| 
 | ||||
| def pytest_funcarg__a(request): | ||||
|     with Writer("request") as writer: | ||||
|         writer.docmethod(request.getfuncargvalue) | ||||
|         writer.docmethod(request.getfixturevalue) | ||||
|         writer.docmethod(request.cached_setup) | ||||
|         writer.docmethod(request.addfinalizer) | ||||
|         writer.docmethod(request.applymarker) | ||||
|  |  | |||
|  | @ -11,9 +11,6 @@ Talks and Tutorials | |||
| Talks and blog postings | ||||
| --------------------------------------------- | ||||
| 
 | ||||
| .. _`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 | ||||
| 
 | ||||
| - `pytest - Rapid Simple Testing, Florian Bruhin, Swiss Python Summit 2016 | ||||
|   <https://www.youtube.com/watch?v=rCBHkQ_LVIs>`_. | ||||
| 
 | ||||
|  | @ -52,12 +49,14 @@ Talks and blog postings | |||
| - `pytest introduction from Brian Okken (January 2013) | ||||
|   <http://pythontesting.net/framework/pytest-introduction/>`_ | ||||
| 
 | ||||
| - `monkey patching done right`_ (blog post, consult `monkeypatch | ||||
|   plugin`_ for up-to-date API) | ||||
| - pycon australia 2012 pytest talk from Brianna Laugher (`video <http://www.youtube.com/watch?v=DTNejE9EraI>`_, `slides <http://www.slideshare.net/pfctdayelise/funcargs-other-fun-with-pytest>`_, `code <https://gist.github.com/3386951>`_) | ||||
| - `pycon 2012 US talk video from Holger Krekel <http://www.youtube.com/watch?v=9LVqBQcFmyw>`_ | ||||
| 
 | ||||
| - `monkey patching done right`_ (blog post, consult `monkeypatch plugin`_ for up-to-date API) | ||||
| 
 | ||||
| Test parametrization: | ||||
| 
 | ||||
| - `generating parametrized tests with funcargs`_ (uses deprecated ``addcall()`` API. | ||||
| - `generating parametrized tests with fixtures`_. | ||||
| - `test generators and cached setup`_ | ||||
| - `parametrizing tests, generalized`_ (blog post) | ||||
| - `putting test-hooks into local or global plugins`_ (blog post) | ||||
|  | @ -78,39 +77,17 @@ Plugin specific examples: | |||
| - `many examples in the docs for plugins`_ | ||||
| 
 | ||||
| .. _`skipping slow tests by default in pytest`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html | ||||
| .. _`many examples in the docs for plugins`: plugin/index.html | ||||
| .. _`monkeypatch plugin`: plugin/monkeypatch.html | ||||
| .. _`application setup in test functions with funcargs`: funcargs.html#appsetup | ||||
| .. _`many examples in the docs for plugins`: plugins.html | ||||
| .. _`monkeypatch plugin`: monkeypatch.html | ||||
| .. _`application setup in test functions with fixtures`: fixture.html#interdependent-fixtures | ||||
| .. _`simultaneously test your code on all platforms`: http://tetamap.wordpress.com/2009/03/23/new-simultanously-test-your-code-on-all-platforms/ | ||||
| .. _`monkey patching done right`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/ | ||||
| .. _`putting test-hooks into local or global plugins`: http://tetamap.wordpress.com/2009/05/14/putting-test-hooks-into-local-and-global-plugins/ | ||||
| .. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/ | ||||
| .. _`generating parametrized tests with funcargs`: funcargs.html#test-generators | ||||
| .. _`generating parametrized tests with fixtures`: parametrize.html#test-generators | ||||
| .. _`test generators and cached setup`: http://bruynooghe.blogspot.com/2010/06/pytest-test-generators-and-cached-setup.html | ||||
| 
 | ||||
| Older conference talks and tutorials | ||||
| ---------------------------------------- | ||||
| 
 | ||||
| - `pycon australia 2012 pytest talk from Brianna Laugher | ||||
|   <http://2012.pycon-au.org/schedule/52/view_talk?day=sunday>`_ (`video <http://www.youtube.com/watch?v=DTNejE9EraI>`_, `slides <http://www.slideshare.net/pfctdayelise/funcargs-other-fun-with-pytest>`_, `code <https://gist.github.com/3386951>`_) | ||||
| - `pycon 2012 US talk video from Holger Krekel <http://www.youtube.com/watch?v=9LVqBQcFmyw>`_ | ||||
| - `pycon 2010 tutorial PDF`_ and `tutorial1 repository`_ | ||||
| 
 | ||||
| - `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009): | ||||
| 
 | ||||
|   - testing terminology | ||||
|   - basic pytest usage, file system layout | ||||
|   - test function arguments (funcargs_) and test fixtures | ||||
|   - existing plugins | ||||
|   - distributed testing | ||||
| 
 | ||||
| - `ep2009-pytest.pdf`_ 60 minute pytest talk, highlighting unique features and a roadmap (July 2009) | ||||
| 
 | ||||
| - `pycon2009-pytest-introduction.zip`_ slides and files, extended version of pytest basic introduction, discusses more options, also introduces old-style xUnit setup, looponfailing and other features. | ||||
| 
 | ||||
| - `pycon2009-pytest-advanced.pdf`_ contain a slightly older version of funcargs and distributed testing, compared to the EuroPython 2009 slides. | ||||
| 
 | ||||
| .. _`ep2009-rapidtesting.pdf`: http://codespeak.net/download/py/ep2009-rapidtesting.pdf | ||||
| .. _`ep2009-pytest.pdf`: http://codespeak.net/download/py/ep2009-pytest.pdf | ||||
| .. _`pycon2009-pytest-introduction.zip`: http://codespeak.net/download/py/pycon2009-pytest-introduction.zip | ||||
| .. _`pycon2009-pytest-advanced.pdf`: http://codespeak.net/download/py/pycon2009-pytest-advanced.pdf | ||||
|  |  | |||
|  | @ -79,7 +79,7 @@ than ``--tb=long``). It also ensures that a stack trace is printed on | |||
| **KeyboardInterrrupt** (Ctrl+C). | ||||
| This is very useful if the tests are taking too long and you interrupt them | ||||
| with Ctrl+C to find out where the tests are *hanging*. By default no output | ||||
| will be shown (because KeyboardInterrupt is catched by pytest). By using this | ||||
| will be shown (because KeyboardInterrupt is caught by pytest). By using this | ||||
| option you make sure a trace is shown. | ||||
| 
 | ||||
| Dropping to PDB_ (Python Debugger) on failures | ||||
|  |  | |||
|  | @ -384,7 +384,7 @@ class TestFormattedExcinfo: | |||
|     def pytest_funcarg__importasmod(self, request): | ||||
|         def importasmod(source): | ||||
|             source = _pytest._code.Source(source) | ||||
|             tmpdir = request.getfuncargvalue("tmpdir") | ||||
|             tmpdir = request.getfixturevalue("tmpdir") | ||||
|             modpath = tmpdir.join("mod.py") | ||||
|             tmpdir.ensure("__init__.py") | ||||
|             modpath.write(source) | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ if __name__ == '__main__': | |||
|     setup( | ||||
|         name="runtests", | ||||
|         version="0.1", | ||||
|         description="exemple of how embedding pytest into an executable using cx_freeze", | ||||
|         description="example of how embedding pytest into an executable using cx_freeze", | ||||
|         executables=[Executable("runtests_script.py")], | ||||
|         options={"build_exe": {'includes': pytest.freeze_includes()}}, | ||||
|     ) | ||||
|  |  | |||
|  | @ -93,12 +93,12 @@ class TestFillFixtures: | |||
|         sub1.join("conftest.py").write(_pytest._code.Source(""" | ||||
|             import pytest | ||||
|             def pytest_funcarg__arg1(request): | ||||
|                 pytest.raises(Exception, "request.getfuncargvalue('arg2')") | ||||
|                 pytest.raises(Exception, "request.getfixturevalue('arg2')") | ||||
|         """)) | ||||
|         sub2.join("conftest.py").write(_pytest._code.Source(""" | ||||
|             import pytest | ||||
|             def pytest_funcarg__arg2(request): | ||||
|                 pytest.raises(Exception, "request.getfuncargvalue('arg1')") | ||||
|                 pytest.raises(Exception, "request.getfixturevalue('arg1')") | ||||
|         """)) | ||||
| 
 | ||||
|         sub1.join("test_in_sub1.py").write("def test_1(arg1): pass") | ||||
|  | @ -435,21 +435,23 @@ class TestRequestBasic: | |||
|         assert len(arg2fixturedefs) == 1 | ||||
|         assert arg2fixturedefs[0].__name__ == "pytest_funcarg__something" | ||||
| 
 | ||||
|     def test_getfuncargvalue_recursive(self, testdir): | ||||
|     def test_getfixturevalue_recursive(self, testdir): | ||||
|         testdir.makeconftest(""" | ||||
|             def pytest_funcarg__something(request): | ||||
|                 return 1 | ||||
|         """) | ||||
|         testdir.makepyfile(""" | ||||
|             def pytest_funcarg__something(request): | ||||
|                 return request.getfuncargvalue("something") + 1 | ||||
|                 return request.getfixturevalue("something") + 1 | ||||
|             def test_func(something): | ||||
|                 assert something == 2 | ||||
|         """) | ||||
|         reprec = testdir.inline_run() | ||||
|         reprec.assertoutcome(passed=1) | ||||
| 
 | ||||
|     def test_getfuncargvalue(self, testdir): | ||||
|     @pytest.mark.parametrize( | ||||
|         'getfixmethod', ('getfixturevalue', 'getfuncargvalue')) | ||||
|     def test_getfixturevalue(self, testdir, getfixmethod): | ||||
|         item = testdir.getitem(""" | ||||
|             l = [2] | ||||
|             def pytest_funcarg__something(request): return 1 | ||||
|  | @ -458,14 +460,15 @@ class TestRequestBasic: | |||
|             def test_func(something): pass | ||||
|         """) | ||||
|         req = item._request | ||||
|         pytest.raises(FixtureLookupError, req.getfuncargvalue, "notexists") | ||||
|         val = req.getfuncargvalue("something") | ||||
|         fixture_fetcher = getattr(req, getfixmethod) | ||||
|         pytest.raises(FixtureLookupError, fixture_fetcher, "notexists") | ||||
|         val = fixture_fetcher("something") | ||||
|         assert val == 1 | ||||
|         val = req.getfuncargvalue("something") | ||||
|         val = fixture_fetcher("something") | ||||
|         assert val == 1 | ||||
|         val2 = req.getfuncargvalue("other") | ||||
|         val2 = fixture_fetcher("other") | ||||
|         assert val2 == 2 | ||||
|         val2 = req.getfuncargvalue("other")  # see about caching | ||||
|         val2 = fixture_fetcher("other")  # see about caching | ||||
|         assert val2 == 2 | ||||
|         pytest._fillfuncargs(item) | ||||
|         assert item.funcargs["something"] == 1 | ||||
|  | @ -812,10 +815,10 @@ class TestRequestCachedSetup: | |||
|             "*1 passed*" | ||||
|         ]) | ||||
| 
 | ||||
|     def test_request_cached_setup_getfuncargvalue(self, testdir): | ||||
|     def test_request_cached_setup_getfixturevalue(self, testdir): | ||||
|         testdir.makepyfile(""" | ||||
|             def pytest_funcarg__arg1(request): | ||||
|                 arg1 = request.getfuncargvalue("arg2") | ||||
|                 arg1 = request.getfixturevalue("arg2") | ||||
|                 return request.cached_setup(lambda: arg1 + 1) | ||||
|             def pytest_funcarg__arg2(request): | ||||
|                 return request.cached_setup(lambda: 10) | ||||
|  | @ -1118,7 +1121,7 @@ class TestFixtureUsages: | |||
| 
 | ||||
| class TestFixtureManagerParseFactories: | ||||
|     def pytest_funcarg__testdir(self, request): | ||||
|         testdir = request.getfuncargvalue("testdir") | ||||
|         testdir = request.getfixturevalue("testdir") | ||||
|         testdir.makeconftest(""" | ||||
|             def pytest_funcarg__hello(request): | ||||
|                 return "conftest" | ||||
|  | @ -1804,9 +1807,9 @@ class TestFixtureMarker: | |||
|         reprec.assertoutcome(passed=4) | ||||
| 
 | ||||
|     @pytest.mark.parametrize("method", [ | ||||
|         'request.getfuncargvalue("arg")', | ||||
|         'request.getfixturevalue("arg")', | ||||
|         'request.cached_setup(lambda: None, scope="function")', | ||||
|     ], ids=["getfuncargvalue", "cached_setup"]) | ||||
|     ], ids=["getfixturevalue", "cached_setup"]) | ||||
|     def test_scope_mismatch_various(self, testdir, method): | ||||
|         testdir.makeconftest(""" | ||||
|             import pytest | ||||
|  | @ -2718,6 +2721,7 @@ class TestContextManagerFixtureFuncs: | |||
|         """.format(flavor=flavor)) | ||||
|         result = testdir.runpytest("-s") | ||||
|         result.stdout.fnmatch_lines("*mew*") | ||||
| 
 | ||||
| class TestParameterizedSubRequest: | ||||
|     def test_call_from_fixture(self, testdir): | ||||
|         testfile = testdir.makepyfile(""" | ||||
|  | @ -2729,7 +2733,7 @@ class TestParameterizedSubRequest: | |||
| 
 | ||||
|             @pytest.fixture | ||||
|             def get_named_fixture(request): | ||||
|                 return request.getfuncargvalue('fix_with_param') | ||||
|                 return request.getfixturevalue('fix_with_param') | ||||
| 
 | ||||
|             def test_foo(request, get_named_fixture): | ||||
|                 pass | ||||
|  | @ -2754,7 +2758,7 @@ class TestParameterizedSubRequest: | |||
|                 return request.param | ||||
| 
 | ||||
|             def test_foo(request): | ||||
|                 request.getfuncargvalue('fix_with_param') | ||||
|                 request.getfixturevalue('fix_with_param') | ||||
|             """) | ||||
|         result = testdir.runpytest() | ||||
|         result.stdout.fnmatch_lines(""" | ||||
|  | @ -2778,7 +2782,7 @@ class TestParameterizedSubRequest: | |||
| 
 | ||||
|         testfile = testdir.makepyfile(""" | ||||
|             def test_foo(request): | ||||
|                 request.getfuncargvalue('fix_with_param') | ||||
|                 request.getfixturevalue('fix_with_param') | ||||
|             """) | ||||
|         result = testdir.runpytest() | ||||
|         result.stdout.fnmatch_lines(""" | ||||
|  | @ -2808,7 +2812,7 @@ class TestParameterizedSubRequest: | |||
|             from fix import fix_with_param | ||||
| 
 | ||||
|             def test_foo(request): | ||||
|                 request.getfuncargvalue('fix_with_param') | ||||
|                 request.getfixturevalue('fix_with_param') | ||||
|             """)) | ||||
| 
 | ||||
|         tests_dir.chdir() | ||||
|  | @ -2823,3 +2827,7 @@ class TestParameterizedSubRequest: | |||
|             E*{1}:5 | ||||
|             *1 failed* | ||||
|             """.format(fixfile.strpath, testfile.basename)) | ||||
| 
 | ||||
| 
 | ||||
| def test_getfuncargvalue_is_deprecated(request): | ||||
|     pytest.deprecated_call(request.getfuncargvalue, 'tmpdir') | ||||
|  |  | |||
|  | @ -749,14 +749,14 @@ class TestMetafuncFunctional: | |||
|             "*4 failed*", | ||||
|         ]) | ||||
| 
 | ||||
|     def test_parametrize_and_inner_getfuncargvalue(self, testdir): | ||||
|     def test_parametrize_and_inner_getfixturevalue(self, testdir): | ||||
|         p = testdir.makepyfile(""" | ||||
|             def pytest_generate_tests(metafunc): | ||||
|                 metafunc.parametrize("arg1", [1], indirect=True) | ||||
|                 metafunc.parametrize("arg2", [10], indirect=True) | ||||
| 
 | ||||
|             def pytest_funcarg__arg1(request): | ||||
|                 x = request.getfuncargvalue("arg2") | ||||
|                 x = request.getfixturevalue("arg2") | ||||
|                 return x + request.param | ||||
| 
 | ||||
|             def pytest_funcarg__arg2(request): | ||||
|  |  | |||
|  | @ -213,10 +213,12 @@ class TestAssertionRewrite: | |||
|             return False | ||||
|         def f(): | ||||
|             assert x() and x() | ||||
|         assert getmsg(f, {"x" : x}) == "assert (x())" | ||||
|         assert getmsg(f, {"x" : x}) == """assert (False) | ||||
|  +  where False = x()""" | ||||
|         def f(): | ||||
|             assert False or x() | ||||
|         assert getmsg(f, {"x" : x}) == "assert (False or x())" | ||||
|         assert getmsg(f, {"x" : x}) == """assert (False or False) | ||||
|  +  where False = x()""" | ||||
|         def f(): | ||||
|             assert 1 in {} and 2 in {} | ||||
|         assert getmsg(f) == "assert (1 in {})" | ||||
|  | @ -299,27 +301,34 @@ class TestAssertionRewrite: | |||
|         ns = {"g" : g} | ||||
|         def f(): | ||||
|             assert g() | ||||
|         assert getmsg(f, ns) == """assert g()""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = g()""" | ||||
|         def f(): | ||||
|             assert g(1) | ||||
|         assert getmsg(f, ns) == """assert g(1)""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = g(1)""" | ||||
|         def f(): | ||||
|             assert g(1, 2) | ||||
|         assert getmsg(f, ns) == """assert g(1, 2)""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = g(1, 2)""" | ||||
|         def f(): | ||||
|             assert g(1, g=42) | ||||
|         assert getmsg(f, ns) == """assert g(1, g=42)""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = g(1, g=42)""" | ||||
|         def f(): | ||||
|             assert g(1, 3, g=23) | ||||
|         assert getmsg(f, ns) == """assert g(1, 3, g=23)""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = g(1, 3, g=23)""" | ||||
|         def f(): | ||||
|             seq = [1, 2, 3] | ||||
|             assert g(*seq) | ||||
|         assert getmsg(f, ns) == """assert g(*[1, 2, 3])""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = g(*[1, 2, 3])""" | ||||
|         def f(): | ||||
|             x = "a" | ||||
|             assert g(**{x : 2}) | ||||
|         assert getmsg(f, ns) == """assert g(**{'a': 2})""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = g(**{'a': 2})""" | ||||
| 
 | ||||
|     def test_attribute(self): | ||||
|         class X(object): | ||||
|  | @ -332,7 +341,8 @@ class TestAssertionRewrite: | |||
|         def f(): | ||||
|             x.a = False  # noqa | ||||
|             assert x.a   # noqa | ||||
|         assert getmsg(f, ns) == """assert x.a""" | ||||
|         assert getmsg(f, ns) == """assert False | ||||
|  +  where False = x.a""" | ||||
| 
 | ||||
|     def test_comparisons(self): | ||||
|         def f(): | ||||
|  | @ -746,5 +756,28 @@ def test_issue731(testdir): | |||
|     assert 'unbalanced braces' not in result.stdout.str() | ||||
| 
 | ||||
| 
 | ||||
| def test_collapse_false_unbalanced_braces(): | ||||
|     util._collapse_false('some text{ False\n{False = some more text\n}') | ||||
| class TestIssue925(): | ||||
|     def test_simple_case(self, testdir): | ||||
|         testdir.makepyfile(""" | ||||
|         def test_ternary_display(): | ||||
|             assert (False == False) == False | ||||
|         """) | ||||
|         result = testdir.runpytest() | ||||
|         result.stdout.fnmatch_lines('*E*assert (False == False) == False') | ||||
| 
 | ||||
|     def test_long_case(self, testdir): | ||||
|         testdir.makepyfile(""" | ||||
|         def test_ternary_display(): | ||||
|              assert False == (False == True) == True | ||||
|         """) | ||||
|         result = testdir.runpytest() | ||||
|         result.stdout.fnmatch_lines('*E*assert (False == True) == True') | ||||
| 
 | ||||
|     def test_many_brackets(self, testdir): | ||||
|         testdir.makepyfile(""" | ||||
|             def test_ternary_display(): | ||||
|                  assert True == ((False == True) == True) | ||||
|             """) | ||||
|         result = testdir.runpytest() | ||||
|         result.stdout.fnmatch_lines('*E*assert True == ((False == True) == True)') | ||||
| 
 | ||||
|  |  | |||
|  | @ -391,6 +391,23 @@ def test_preparse_ordering_with_setuptools(testdir, monkeypatch): | |||
|     plugin = config.pluginmanager.getplugin("mytestplugin") | ||||
|     assert plugin.x == 42 | ||||
| 
 | ||||
| 
 | ||||
| def test_setuptools_importerror_issue1479(testdir, monkeypatch): | ||||
|     pkg_resources = pytest.importorskip("pkg_resources") | ||||
|     def my_iter(name): | ||||
|         assert name == "pytest11" | ||||
|         class EntryPoint: | ||||
|             name = "mytestplugin" | ||||
|             dist = None | ||||
|             def load(self): | ||||
|                 raise ImportError("Don't hide me!") | ||||
|         return iter([EntryPoint()]) | ||||
| 
 | ||||
|     monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) | ||||
|     with pytest.raises(ImportError): | ||||
|         testdir.parseconfig() | ||||
| 
 | ||||
| 
 | ||||
| def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch): | ||||
|     pkg_resources = pytest.importorskip("pkg_resources") | ||||
|     def my_iter(name): | ||||
|  |  | |||
|  | @ -29,6 +29,9 @@ class TestParser: | |||
|         assert argument.dest == 'test' | ||||
|         argument = parseopt.Argument('-t', '--test', dest='abc') | ||||
|         assert argument.dest == 'abc' | ||||
|         assert str(argument) == ( | ||||
|             "Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')" | ||||
|         ) | ||||
| 
 | ||||
|     def test_argument_type(self): | ||||
|         argument = parseopt.Argument('-t', dest='abc', type='int') | ||||
|  |  | |||
|  | @ -13,11 +13,11 @@ def runpdb_and_get_report(testdir, source): | |||
| 
 | ||||
| class TestPDB: | ||||
|     def pytest_funcarg__pdblist(self, request): | ||||
|         monkeypatch = request.getfuncargvalue("monkeypatch") | ||||
|         monkeypatch = request.getfixturevalue("monkeypatch") | ||||
|         pdblist = [] | ||||
|         def mypdb(*args): | ||||
|             pdblist.append(args) | ||||
|         plugin = request.config.pluginmanager.getplugin('pdb') | ||||
|         plugin = request.config.pluginmanager.getplugin('debugging') | ||||
|         monkeypatch.setattr(plugin, 'post_mortem', mypdb) | ||||
|         return pdblist | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue