Merge branch 'pytest-dev'
# Conflicts: # AUTHORS
This commit is contained in:
@@ -46,7 +46,7 @@ installall: clean install installpdf
|
||||
@echo "done"
|
||||
|
||||
regen:
|
||||
PYTHONDONTWRITEBYTECODE=1 COLUMNS=76 regendoc --update *.txt */*.txt
|
||||
PYTHONDONTWRITEBYTECODE=1 COLUMNS=76 regendoc --update *.rst */*.rst
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
|
||||
@@ -6,7 +6,7 @@ def get_version_string():
|
||||
fn = py.path.local(__file__).join("..", "..", "..",
|
||||
"_pytest", "__init__.py")
|
||||
for line in fn.readlines():
|
||||
if "version" in line:
|
||||
if "version" in line and not line.strip().startswith('#'):
|
||||
return eval(line.split("=")[-1])
|
||||
|
||||
def get_minor_version_string():
|
||||
|
||||
27
doc/en/apiref.rst
Normal file
27
doc/en/apiref.rst
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
.. _apiref:
|
||||
|
||||
pytest reference documentation
|
||||
================================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
builtin
|
||||
customize
|
||||
assert
|
||||
fixture
|
||||
yieldfixture
|
||||
parametrize
|
||||
xunit_setup
|
||||
capture
|
||||
monkeypatch
|
||||
xdist
|
||||
tmpdir
|
||||
mark
|
||||
skipping
|
||||
recwarn
|
||||
unittest
|
||||
nose
|
||||
doctest
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
.. _apiref:
|
||||
|
||||
pytest reference documentation
|
||||
================================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
builtin.txt
|
||||
customize.txt
|
||||
assert.txt
|
||||
fixture.txt
|
||||
yieldfixture.txt
|
||||
parametrize.txt
|
||||
xunit_setup.txt
|
||||
capture.txt
|
||||
monkeypatch.txt
|
||||
xdist.txt
|
||||
tmpdir.txt
|
||||
mark.txt
|
||||
skipping.txt
|
||||
recwarn.txt
|
||||
unittest.txt
|
||||
nose.txt
|
||||
doctest.txt
|
||||
|
||||
@@ -114,6 +114,16 @@ like documenting unfixed bugs (where the test describes what "should" happen)
|
||||
or bugs in dependencies.
|
||||
|
||||
|
||||
.. _`assertwarns`:
|
||||
|
||||
Assertions about expected warnings
|
||||
-----------------------------------------
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
You can check that code raises a particular warning using
|
||||
:ref:`pytest.warns <warns>`.
|
||||
|
||||
|
||||
.. _newreport:
|
||||
|
||||
@@ -228,9 +238,7 @@ Reporting details about a failing assertion is achieved either by rewriting
|
||||
assert statements before they are run or re-evaluating the assert expression and
|
||||
recording the intermediate values. Which technique is used depends on the
|
||||
location of the assert, ``pytest`` configuration, and Python version being used
|
||||
to run ``pytest``. Note that for assert statements with a manually provided
|
||||
message, i.e. ``assert expr, message``, no assertion introspection takes place
|
||||
and the manually provided message will be rendered in tracebacks.
|
||||
to run ``pytest``.
|
||||
|
||||
By default, if the Python version is greater than or equal to 2.6, ``pytest``
|
||||
rewrites assert statements in test modules. Rewritten assert statements put
|
||||
@@ -47,7 +47,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.autosummary',
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.txt'
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
@@ -73,13 +73,13 @@ copyright = u'2015, holger krekel and pytest-dev team'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['links.inc', '_build', 'naming20.txt', 'test/*',
|
||||
exclude_patterns = ['links.inc', '_build', 'naming20.rst', 'test/*',
|
||||
"old_*",
|
||||
'*attic*',
|
||||
'*/attic*',
|
||||
'funcargs.txt',
|
||||
'setup.txt',
|
||||
'example/remoteinterp.txt',
|
||||
'funcargs.rst',
|
||||
'setup.rst',
|
||||
'example/remoteinterp.rst',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ Full pytest documentation
|
||||
example/index
|
||||
talks
|
||||
contributing
|
||||
funcarg_compare.txt
|
||||
funcarg_compare
|
||||
announce/index
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
changelog.txt
|
||||
changelog
|
||||
|
||||
@@ -219,3 +219,10 @@ Builtin configuration file options
|
||||
|
||||
One or more doctest flag names from the standard ``doctest`` module.
|
||||
:doc:`See how py.test handles doctests <doctest>`.
|
||||
|
||||
.. confval:: confcutdir
|
||||
|
||||
Sets a directory where search upwards for ``conftest.py`` files stops.
|
||||
By default, pytest will stop searching for ``conftest.py`` files upwards
|
||||
from ``pytest.ini``/``tox.ini``/``setup.cfg`` of the project if any,
|
||||
or up to the file-system root.
|
||||
@@ -72,3 +72,18 @@ ignore lengthy exception stack traces you can just write::
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
|
||||
|
||||
|
||||
py.test also introduces a new ``ALLOW_UNICODE`` option flag: when enabled, the
|
||||
``u`` prefix is stripped from unicode strings in expected doctest output. This
|
||||
allows doctests which use unicode to run in Python 2 and 3 unchanged.
|
||||
|
||||
As with any other option flag, this flag can be enabled in ``pytest.ini`` using
|
||||
the ``doctest_optionflags`` ini option or by an inline comment in the doc test
|
||||
itself::
|
||||
|
||||
# content of example.rst
|
||||
>>> get_unicode_greeting() # doctest: +ALLOW_UNICODE
|
||||
'Hello'
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ The following examples aim at various use cases you might encounter.
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
reportingdemo.txt
|
||||
simple.txt
|
||||
parametrize.txt
|
||||
markers.txt
|
||||
special.txt
|
||||
pythoncollection.txt
|
||||
nonpython.txt
|
||||
reportingdemo
|
||||
simple
|
||||
parametrize
|
||||
markers
|
||||
special
|
||||
pythoncollection
|
||||
nonpython
|
||||
@@ -81,7 +81,7 @@ Numbers, strings, booleans and None will have their usual string representation
|
||||
used in the test ID. For other objects, pytest will make a string based on
|
||||
the argument name::
|
||||
|
||||
# contents of test_time.py
|
||||
# content of test_time.py
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
@@ -534,23 +534,24 @@ case we just write some informations out to a ``failures`` file::
|
||||
import pytest
|
||||
import os.path
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_makereport(item, call, __multicall__):
|
||||
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
# execute all other hooks to obtain the report object
|
||||
rep = __multicall__.execute()
|
||||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
|
||||
# we only look at actual failing test calls, not setup/teardown
|
||||
if rep.when == "call" and rep.failed:
|
||||
mode = "a" if os.path.exists("failures") else "w"
|
||||
with open("failures", mode) as f:
|
||||
# let's also access a fixture for the fun of it
|
||||
if "tmpdir" in item.funcargs:
|
||||
if "tmpdir" in item.fixturenames:
|
||||
extra = " (%s)" % item.funcargs["tmpdir"]
|
||||
else:
|
||||
extra = ""
|
||||
|
||||
f.write(rep.nodeid + extra + "\n")
|
||||
return rep
|
||||
|
||||
|
||||
if you then have failing tests::
|
||||
|
||||
@@ -606,16 +607,16 @@ here is a little example implemented via a local plugin::
|
||||
|
||||
import pytest
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_makereport(item, call, __multicall__):
|
||||
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
# execute all other hooks to obtain the report object
|
||||
rep = __multicall__.execute()
|
||||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
|
||||
# set an report attribute for each phase of a call, which can
|
||||
# be "setup", "call", "teardown"
|
||||
|
||||
setattr(item, "rep_" + rep.when, rep)
|
||||
return rep
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -742,5 +743,4 @@ over to ``pytest`` instead. For example::
|
||||
This makes it convenient to execute your tests from within your frozen
|
||||
application, using standard ``py.test`` command-line options::
|
||||
|
||||
$ ./app_main --pytest --verbose --tb=long --junit-xml=results.xml test-suite/
|
||||
/bin/sh: ./app_main: No such file or directory
|
||||
./app_main --pytest --verbose --tb=long --junit-xml=results.xml test-suite/
|
||||
@@ -154,8 +154,8 @@ to create a JUnitXML file that Jenkins_ can pick up and generate reports.
|
||||
.. _standalone:
|
||||
.. _`genscript method`:
|
||||
|
||||
Create a pytest standalone script
|
||||
-------------------------------------------
|
||||
(deprecated) Create a pytest standalone script
|
||||
-----------------------------------------------
|
||||
|
||||
If you are a maintainer or application developer and want people
|
||||
who don't deal with python much to easily run tests you may generate
|
||||
@@ -5,10 +5,10 @@ Getting started basics
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
index.txt
|
||||
getting-started.txt
|
||||
usage.txt
|
||||
goodpractises.txt
|
||||
projects.txt
|
||||
faq.txt
|
||||
index
|
||||
getting-started
|
||||
usage
|
||||
goodpractises
|
||||
projects
|
||||
faq
|
||||
|
||||
@@ -114,6 +114,18 @@ Let's run this::
|
||||
The one parameter set which caused a failure previously now
|
||||
shows up as an "xfailed (expected to fail)" test.
|
||||
|
||||
To get all combinations of multiple parametrized arguments you can stack
|
||||
``parametrize`` decorators::
|
||||
|
||||
import pytest
|
||||
@pytest.mark.parametrize("x", [0, 1])
|
||||
@pytest.mark.parametrize("y", [2, 3])
|
||||
def test_foo(x, y):
|
||||
pass
|
||||
|
||||
This will run the test with the arguments set to x=0/y=2, x=0/y=3, x=1/y=2 and
|
||||
x=1/y=3.
|
||||
|
||||
.. note::
|
||||
|
||||
In versions prior to 2.4 one needed to specify the argument
|
||||
116
doc/en/recwarn.rst
Normal file
116
doc/en/recwarn.rst
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
Asserting Warnings
|
||||
=====================================================
|
||||
|
||||
.. _warns:
|
||||
|
||||
Asserting warnings with the warns function
|
||||
-----------------------------------------------
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
You can check that code raises a particular warning using ``pytest.warns``,
|
||||
which works in a similar manner to :ref:`raises <assertraises>`::
|
||||
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
def test_warning():
|
||||
with pytest.warns(UserWarning):
|
||||
warnings.warn("my warning", UserWarning)
|
||||
|
||||
The test will fail if the warning in question is not raised.
|
||||
|
||||
You can also call ``pytest.warns`` on a function or code string::
|
||||
|
||||
pytest.warns(expected_warning, func, *args, **kwargs)
|
||||
pytest.warns(expected_warning, "func(*args, **kwargs)")
|
||||
|
||||
The function also returns a list of all raised warnings (as
|
||||
``warnings.WarningMessage`` objects), which you can query for
|
||||
additional information::
|
||||
|
||||
with pytest.warns(RuntimeWarning) as record:
|
||||
warnings.warn("another warning", RuntimeWarning)
|
||||
|
||||
# check that only one warning was raised
|
||||
assert len(record) == 1
|
||||
# check that the message matches
|
||||
assert record[0].message.args[0] == "another warning"
|
||||
|
||||
Alternatively, you can examine raised warnings in detail using the
|
||||
:ref:`recwarn <recwarn>` fixture (see below).
|
||||
|
||||
.. _recwarn:
|
||||
|
||||
Recording warnings
|
||||
------------------------
|
||||
|
||||
You can record raised warnings either using ``pytest.warns`` or with
|
||||
the ``recwarn`` fixture.
|
||||
|
||||
To record with ``pytest.warns`` without asserting anything about the warnings,
|
||||
pass ``None`` as the expected warning type::
|
||||
|
||||
with pytest.warns(None) as record:
|
||||
warnings.warn("user", UserWarning)
|
||||
warnings.warn("runtime", RuntimeWarning)
|
||||
|
||||
assert len(record) == 2
|
||||
assert str(record[0].message) == "user"
|
||||
assert str(record[1].message) == "runtime"
|
||||
|
||||
The ``recwarn`` fixture will record warnings for the whole function::
|
||||
|
||||
import warnings
|
||||
|
||||
def test_hello(recwarn):
|
||||
warnings.warn("hello", UserWarning)
|
||||
assert len(recwarn) == 1
|
||||
w = recwarn.pop(UserWarning)
|
||||
assert issubclass(w.category, UserWarning)
|
||||
assert str(w.message) == "hello"
|
||||
assert w.filename
|
||||
assert w.lineno
|
||||
|
||||
Both ``recwarn`` and ``pytest.warns`` return the same interface for recorded
|
||||
warnings: a WarningsRecorder instance. To view the recorded warnings, you can
|
||||
iterate over this instance, call ``len`` on it to get the number of recorded
|
||||
warnings, or index into it to get a particular recorded warning. It also
|
||||
provides these methods:
|
||||
|
||||
.. autoclass:: _pytest.recwarn.WarningsRecorder()
|
||||
:members:
|
||||
|
||||
Each recorded warning has the attributes ``message``, ``category``,
|
||||
``filename``, ``lineno``, ``file``, and ``line``. The ``category`` is the
|
||||
class of the warning. The ``message`` is the warning itself; calling
|
||||
``str(message)`` will return the actual message of the warning.
|
||||
|
||||
|
||||
.. _ensuring_function_triggers:
|
||||
|
||||
Ensuring a function triggers a deprecation warning
|
||||
-------------------------------------------------------
|
||||
|
||||
You can also call a global helper for checking
|
||||
that a certain function call triggers a ``DeprecationWarning``::
|
||||
|
||||
import pytest
|
||||
|
||||
def test_global():
|
||||
pytest.deprecated_call(myfunction, 17)
|
||||
|
||||
By default, deprecation warnings will not be caught when using ``pytest.warns``
|
||||
or ``recwarn``, since the default Python warnings filters hide
|
||||
DeprecationWarnings. If you wish to record them in your own code, use the
|
||||
command ``warnings.simplefilter('always')``::
|
||||
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
def test_deprecation(recwarn):
|
||||
warnings.simplefilter('always')
|
||||
warnings.warn("deprecated", DeprecationWarning)
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
Asserting deprecation and other warnings
|
||||
=====================================================
|
||||
|
||||
.. _function_argument:
|
||||
|
||||
The recwarn function argument
|
||||
------------------------------------
|
||||
|
||||
You can use the ``recwarn`` funcarg to assert that code triggers
|
||||
warnings through the Python warnings system. Here is a simple
|
||||
self-contained test::
|
||||
|
||||
# content of test_recwarn.py
|
||||
def test_hello(recwarn):
|
||||
from warnings import warn
|
||||
warn("hello", DeprecationWarning)
|
||||
w = recwarn.pop(DeprecationWarning)
|
||||
assert issubclass(w.category, DeprecationWarning)
|
||||
assert 'hello' in str(w.message)
|
||||
assert w.filename
|
||||
assert w.lineno
|
||||
|
||||
The ``recwarn`` function argument provides these methods:
|
||||
|
||||
.. method:: pop(category=None)
|
||||
|
||||
Return last warning matching the category.
|
||||
|
||||
.. method:: clear()
|
||||
|
||||
Clear list of warnings
|
||||
|
||||
|
||||
.. _ensuring_function_triggers:
|
||||
|
||||
Ensuring a function triggers a deprecation warning
|
||||
-------------------------------------------------------
|
||||
|
||||
You can also call a global helper for checking
|
||||
that a certain function call triggers a ``DeprecationWarning``::
|
||||
|
||||
import pytest
|
||||
|
||||
def test_global():
|
||||
pytest.deprecated_call(myfunction, 17)
|
||||
@@ -1,54 +0,0 @@
|
||||
pytest release checklist
|
||||
-------------------------
|
||||
|
||||
For doing a release of pytest (status April 2015) this rough checklist is used:
|
||||
|
||||
1. change version numbers in ``_pytest/__init__.py`` to the to-be-released version.
|
||||
(the version number in ``setup.py`` reads from that init file as well)
|
||||
|
||||
2. finalize ``./CHANGELOG`` (don't forget the the header).
|
||||
|
||||
3. write ``doc/en/announce/release-VERSION.txt``
|
||||
(usually copying from an earlier release version).
|
||||
|
||||
4. regenerate doc examples with ``tox -e regen`` and check with ``git diff``
|
||||
if the differences show regressions. It's a bit of a manual process because
|
||||
there a large part of the diff is about pytest headers or differences in
|
||||
speed ("tests took X.Y seconds"). (XXX automate doc/example diffing to ignore
|
||||
such changes and integrate it into "tox -e regen").
|
||||
|
||||
5. ``devpi upload`` to `your developer devpi index <http://doc.devpi.net/latest/quickstart-releaseprocess.html>`_. You can create your own user and index on https://devpi.net,
|
||||
an inofficial service from the devpi authors.
|
||||
|
||||
6. run ``devpi use INDEX`` and ``devpi test`` from linux and windows machines
|
||||
and verify test results on the index. On linux typically all environments
|
||||
pass (April 2015 there is a setup problem with a cx_freeze environment)
|
||||
but on windows all involving ``pexpect`` fail because pexpect does not exist
|
||||
on windows and tox does not allow to have platform-specific environments.
|
||||
Also on windows ``py33-trial`` fails but should probably pass (March 2015).
|
||||
In any case, py26,py27,py33,py34 are required to pass for all platforms.
|
||||
|
||||
7. You can fix tests/code and repeat number 6. until everything passes.
|
||||
|
||||
8. Once you have sufficiently passing tox tests you can do the actual release::
|
||||
|
||||
cd doc/en/
|
||||
make install # will install to 2.7, 2.8, ... according to _pytest/__init__.py
|
||||
make install-pdf # optional, requires latex packages installed
|
||||
ssh pytest-dev@pytest.org # MANUAL: symlink "pytest.org/latest" to the just
|
||||
# installed release docs
|
||||
# browse to pytest.org to see
|
||||
|
||||
devpi push pytest-VERSION pypi:NAME
|
||||
git commit -a -m "... finalized pytest-VERSION"
|
||||
git tag VERSION
|
||||
git push
|
||||
|
||||
9. send out release announcement to pytest-dev@python.org,
|
||||
testing-in-python@lists.idyll.org and python-announce-list@python.org .
|
||||
|
||||
10. **after the release** bump the version number in ``_pytest/__init__.py``,
|
||||
to the next Minor release version (i.e. if you released ``pytest-2.8.0``,
|
||||
set it to ``pytest-2.9.0.dev1``).
|
||||
|
||||
11. already done :)
|
||||
@@ -83,7 +83,7 @@ As with all function :ref:`marking <mark>` you can skip test functions at the
|
||||
`whole class- or module level`_. If your code targets python2.6 or above you
|
||||
use the skipif decorator (and any other marker) on classes::
|
||||
|
||||
@pytest.mark.skipif(sys.platform == 'win32',
|
||||
@pytest.mark.skipif(sys.platform != 'win32',
|
||||
reason="requires windows")
|
||||
class TestPosixCalls:
|
||||
|
||||
@@ -97,7 +97,7 @@ If your code targets python2.5 where class-decorators are not available,
|
||||
you can set the ``pytestmark`` attribute of a class::
|
||||
|
||||
class TestPosixCalls:
|
||||
pytestmark = pytest.mark.skipif(sys.platform == 'win32',
|
||||
pytestmark = pytest.mark.skipif(sys.platform != 'win32',
|
||||
reason="requires Windows")
|
||||
|
||||
def test_function(self):
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
generate standalone test script to be distributed along with an application.
|
||||
(deprecated) generate standalone test script to be distributed along with an application.
|
||||
============================================================================
|
||||
|
||||
|
||||
@@ -153,6 +153,36 @@ integration servers, use this invocation::
|
||||
|
||||
to create an XML file at ``path``.
|
||||
|
||||
record_xml_property
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
If you want to log additional information for a test, you can use the
|
||||
``record_xml_property`` fixture:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_function(record_xml_property):
|
||||
record_xml_property("example_key", 1)
|
||||
assert 0
|
||||
|
||||
This will add an extra property ``example_key="1"`` to the generated
|
||||
``testcase`` tag:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<testcase classname="test_function" example_key="1" file="test_function.py" line="0" name="test_function" time="0.0009">
|
||||
|
||||
.. warning::
|
||||
|
||||
This is an experimental feature, and its interface might be replaced
|
||||
by something more powerful and general in future versions. The
|
||||
functionality per-se will be kept, however.
|
||||
|
||||
Also please note that using this feature will break any schema verification.
|
||||
This might be a problem when used with some CI servers.
|
||||
|
||||
Creating resultlog format files
|
||||
----------------------------------------------------
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user