Merge pull request #1859 from nicoddemus/merge-master-into-features
Merge master into features
This commit is contained in:
commit
6359894fe4
2
AUTHORS
2
AUTHORS
|
@ -48,7 +48,6 @@ Eduardo Schettino
|
|||
Elizaveta Shashkova
|
||||
Endre Galaczi
|
||||
Eric Hunsberger
|
||||
Eric Hunsberger
|
||||
Eric Siegerman
|
||||
Erik M. Bray
|
||||
Feng Ma
|
||||
|
@ -81,6 +80,7 @@ Lukas Bednar
|
|||
Maciek Fijalkowski
|
||||
Maho
|
||||
Marc Schlaich
|
||||
Marcin Bachry
|
||||
Mark Abramowitz
|
||||
Markus Unterwaditzer
|
||||
Martijn Faassen
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
|
||||
|
||||
3.0.1.dev
|
||||
3.0.2.dev
|
||||
=========
|
||||
|
||||
*
|
||||
|
@ -21,6 +21,33 @@
|
|||
|
||||
*
|
||||
|
||||
3.0.1
|
||||
=====
|
||||
|
||||
* Fix regression when ``importorskip`` is used at module level (`#1822`_).
|
||||
Thanks `@jaraco`_ and `@The-Compiler`_ for the report and `@nicoddemus`_ for the PR.
|
||||
|
||||
* Fix parametrization scope when session fixtures are used in conjunction
|
||||
with normal parameters in the same call (`#1832`_).
|
||||
Thanks `@The-Compiler`_ for the report, `@Kingdread`_ and `@nicoddemus`_ for the PR.
|
||||
|
||||
* Fix internal error when parametrizing tests or fixtures using an empty ``ids`` argument (`#1849`_).
|
||||
Thanks `@OPpuolitaival`_ for the report and `@nicoddemus`_ for the PR.
|
||||
|
||||
* Fix loader error when running ``pytest`` embedded in a zipfile.
|
||||
Thanks `@mbachry`_ for the PR.
|
||||
|
||||
|
||||
.. _@Kingdread: https://github.com/Kingdread
|
||||
.. _@mbachry: https://github.com/mbachry
|
||||
.. _@OPpuolitaival: https://github.com/OPpuolitaival
|
||||
|
||||
.. _#1822: https://github.com/pytest-dev/pytest/issues/1822
|
||||
.. _#1832: https://github.com/pytest-dev/pytest/issues/1832
|
||||
.. _#1849: https://github.com/pytest-dev/pytest/issues/1849
|
||||
|
||||
>>>>>>> master
|
||||
|
||||
3.0.0
|
||||
=====
|
||||
|
||||
|
@ -323,10 +350,6 @@ time or change existing behaviors in order to make them less surprising/more use
|
|||
identify bugs in ``conftest.py`` files (`#1516`_). Thanks `@txomon`_ for
|
||||
the PR.
|
||||
|
||||
* Add an 'E' to the first line of error messages from FixtureLookupErrorRepr.
|
||||
Fixes `#717`_. Thanks `@blueyed`_ for reporting, `@eolo999`_ for the PR
|
||||
and `@tomviner`_ for his guidance during EuroPython2016 sprint.
|
||||
|
||||
* Text documents without any doctests no longer appear as "skipped".
|
||||
Thanks `@graingert`_ for reporting and providing a full PR (`#1580`_).
|
||||
|
||||
|
@ -1225,7 +1248,7 @@ time or change existing behaviors in order to make them less surprising/more use
|
|||
dep). Thanks Charles Cloud for analysing the issue.
|
||||
|
||||
- fix conftest related fixture visibility issue: when running with a
|
||||
CWD outside a test package pytest would get fixture discovery wrong.
|
||||
CWD outside of a test package pytest would get fixture discovery wrong.
|
||||
Thanks to Wolfgang Schnerring for figuring out a reproducable example.
|
||||
|
||||
- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
|
||||
|
|
111
HOWTORELEASE.rst
111
HOWTORELEASE.rst
|
@ -3,90 +3,83 @@ How to release pytest
|
|||
|
||||
Note: this assumes you have already registered on pypi.
|
||||
|
||||
0. create the branch release-VERSION
|
||||
use features as base for minor/major releases
|
||||
and master as base for bugfix releases
|
||||
1. Bump version numbers in ``_pytest/__init__.py`` (``setup.py`` reads it).
|
||||
|
||||
1. Bump version numbers in _pytest/__init__.py (setup.py reads it)
|
||||
2. Check and finalize ``CHANGELOG.rst``.
|
||||
|
||||
2. Check and finalize CHANGELOG
|
||||
3. Write ``doc/en/announce/release-VERSION.txt`` and include
|
||||
it in ``doc/en/announce/index.txt``. Run this command to list names of authors involved::
|
||||
|
||||
3. Write doc/en/announce/release-VERSION.txt and include
|
||||
it in doc/en/announce/index.txt::
|
||||
git log $(git describe --abbrev=0 --tags)..HEAD --format='%aN' | sort -u
|
||||
|
||||
git log 2.8.2..HEAD --format='%aN' | sort -u # lists the names of authors involved
|
||||
4. Regenerate the docs examples using tox::
|
||||
|
||||
4. Use devpi for uploading a release tarball to a staging area::
|
||||
tox -e regen
|
||||
|
||||
5. At this point, open a PR named ``release-X`` so others can help find regressions or provide suggestions.
|
||||
|
||||
6. Use devpi for uploading a release tarball to a staging area::
|
||||
|
||||
devpi use https://devpi.net/USER/dev
|
||||
devpi upload --formats sdist,bdist_wheel
|
||||
|
||||
5. Run from multiple machines::
|
||||
7. Run from multiple machines::
|
||||
|
||||
devpi use https://devpi.net/USER/dev
|
||||
devpi test pytest==VERSION
|
||||
|
||||
6. Check that tests pass for relevant combinations with::
|
||||
Alternatively, you can use `devpi-cloud-tester <https://github.com/nicoddemus/devpi-cloud-tester>`_ to test
|
||||
the package on AppVeyor and Travis (follow instructions on the ``README``).
|
||||
|
||||
8. Check that tests pass for relevant combinations with::
|
||||
|
||||
devpi list pytest
|
||||
|
||||
or look at failures with "devpi list -f pytest".
|
||||
|
||||
7. Regenerate the docs examples using tox, and check for regressions::
|
||||
|
||||
tox -e regen
|
||||
git diff
|
||||
|
||||
|
||||
8. Build the docs, you need a virtualenv with py and sphinx
|
||||
installed::
|
||||
|
||||
cd doc/en
|
||||
make html
|
||||
|
||||
Commit any changes before tagging the release.
|
||||
|
||||
9. Tag the release::
|
||||
|
||||
git tag VERSION
|
||||
git push
|
||||
|
||||
10. Upload the docs using doc/en/Makefile::
|
||||
|
||||
cd doc/en
|
||||
make install # or "installall" if you have LaTeX installed for PDF
|
||||
|
||||
This requires ssh-login permission on pytest.org because it uses
|
||||
rsync.
|
||||
Note that the ``install`` target of ``doc/en/Makefile`` defines where the
|
||||
rsync goes to, typically to the "latest" section of pytest.org.
|
||||
|
||||
If you are making a minor release (e.g. 5.4), you also need to manually
|
||||
create a symlink for "latest"::
|
||||
|
||||
ssh pytest-dev@pytest.org
|
||||
ln -s 5.4 latest
|
||||
|
||||
Browse to pytest.org to verify.
|
||||
|
||||
11. Publish to pypi::
|
||||
9. Feeling confident? Publish to pypi::
|
||||
|
||||
devpi push pytest==VERSION pypi:NAME
|
||||
|
||||
where NAME is the name of pypi.python.org as configured in your ``~/.pypirc``
|
||||
file `for devpi <http://doc.devpi.net/latest/quickstart-releaseprocess.html?highlight=pypirc#devpi-push-releasing-to-an-external-index>`_.
|
||||
where NAME is the name of pypi.python.org as configured in your ``~/.pypirc``
|
||||
file `for devpi <http://doc.devpi.net/latest/quickstart-releaseprocess.html?highlight=pypirc#devpi-push-releasing-to-an-external-index>`_.
|
||||
|
||||
10. Tag the release::
|
||||
|
||||
12. Send release announcement to mailing lists:
|
||||
git tag VERSION <hash>
|
||||
git push origin VERSION
|
||||
|
||||
- pytest-dev
|
||||
- testing-in-python
|
||||
Make sure ``<hash>`` is **exactly** the git hash at the time the package was created.
|
||||
|
||||
11. Send release announcement to mailing lists:
|
||||
|
||||
- pytest-dev@python.org
|
||||
- testing-in-python@lists.idyll.org
|
||||
- python-announce-list@python.org
|
||||
|
||||
And announce the release on Twitter, making sure to add the hashtag ``#pytest``.
|
||||
|
||||
12. **After the release**
|
||||
|
||||
a. **patch release (2.8.3)**:
|
||||
|
||||
1. Checkout ``master``.
|
||||
2. Update version number in ``_pytest/__init__.py`` to ``"2.8.4.dev"``.
|
||||
3. Create a new section in ``CHANGELOG.rst`` titled ``2.8.4.dev`` and add a few bullet points as placeholders for new entries.
|
||||
4. Commit and push.
|
||||
|
||||
b. **minor release (2.9.0)**:
|
||||
|
||||
1. Merge ``features`` into ``master``.
|
||||
2. Checkout ``master``.
|
||||
3. Follow the same steps for a **patch release** above, using the next patch release: ``2.9.1.dev``.
|
||||
4. Commit ``master``.
|
||||
5. Checkout ``features`` and merge with ``master`` (should be a fast-forward at this point).
|
||||
6. Update version number in ``_pytest/__init__.py`` to the next minor release: ``"2.10.0.dev"``.
|
||||
7. Create a new section in ``CHANGELOG.rst`` titled ``2.10.0.dev``, above ``2.9.1.dev``, and add a few bullet points as placeholders for new entries.
|
||||
8. Commit ``features``.
|
||||
9. Push ``master`` and ``features``.
|
||||
|
||||
c. **major release (3.0.0)**: same steps as that of a **minor release**
|
||||
|
||||
13. **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``).
|
||||
|
||||
14. merge the actual release into the master branch and do a pull request against it
|
||||
15. merge from master to features
|
||||
|
|
365
ISSUES.txt
365
ISSUES.txt
|
@ -1,365 +0,0 @@
|
|||
|
||||
|
||||
recorder = monkeypatch.function(".......")
|
||||
-------------------------------------------------------------
|
||||
tags: nice feature
|
||||
|
||||
Like monkeypatch.replace but sets a mock-like call recorder:
|
||||
|
||||
recorder = monkeypatch.function("os.path.abspath")
|
||||
recorder.set_return("/hello")
|
||||
os.path.abspath("hello")
|
||||
call, = recorder.calls
|
||||
assert call.args.path == "hello"
|
||||
assert call.returned == "/hello"
|
||||
...
|
||||
|
||||
Unlike mock, "args.path" acts on the parsed auto-spec'ed ``os.path.abspath``
|
||||
so it's independent from if the client side called "os.path.abspath(path=...)"
|
||||
or "os.path.abspath('positional')".
|
||||
|
||||
|
||||
refine parametrize API
|
||||
-------------------------------------------------------------
|
||||
tags: critical feature
|
||||
|
||||
extend metafunc.parametrize to directly support indirection, example:
|
||||
|
||||
def setupdb(request, config):
|
||||
# setup "resource" based on test request and the values passed
|
||||
# in to parametrize. setupfunc is called for each such value.
|
||||
# you may use request.addfinalizer() or request.cached_setup ...
|
||||
return dynamic_setup_database(val)
|
||||
|
||||
@pytest.mark.parametrize("db", ["pg", "mysql"], setupfunc=setupdb)
|
||||
def test_heavy_functional_test(db):
|
||||
...
|
||||
|
||||
There would be no need to write or explain funcarg factories and
|
||||
their special __ syntax.
|
||||
|
||||
The examples and improvements should also show how to put the parametrize
|
||||
decorator to a class, to a module or even to a directory. For the directory
|
||||
part a conftest.py content like this::
|
||||
|
||||
pytestmark = [
|
||||
@pytest.mark.parametrize_setup("db", ...),
|
||||
]
|
||||
|
||||
probably makes sense in order to keep the declarative nature. This mirrors
|
||||
the marker-mechanism with respect to a test module but puts it to a directory
|
||||
scale.
|
||||
|
||||
When doing larger scoped parametrization it probably becomes necessary
|
||||
to allow parametrization to be ignored if the according parameter is not
|
||||
used (currently any parametrized argument that is not present in a function will cause a ValueError). Example:
|
||||
|
||||
@pytest.mark.parametrize("db", ..., mustmatch=False)
|
||||
|
||||
means to not raise an error but simply ignore the parametrization
|
||||
if the signature of a decorated function does not match. XXX is it
|
||||
not sufficient to always allow non-matches?
|
||||
|
||||
|
||||
allow parametrized attributes on classes
|
||||
--------------------------------------------------
|
||||
|
||||
tags: wish 2.4
|
||||
|
||||
example:
|
||||
|
||||
@pytest.mark.parametrize_attr("db", setupfunc, [1,2,3], scope="class")
|
||||
@pytest.mark.parametrize_attr("tmp", setupfunc, scope="...")
|
||||
class TestMe:
|
||||
def test_hello(self):
|
||||
access self.db ...
|
||||
|
||||
this would run the test_hello() function three times with three
|
||||
different values for self.db. This could also work with unittest/nose
|
||||
style tests, i.e. it leverages existing test suites without needing
|
||||
to rewrite them. Together with the previously mentioned setup_test()
|
||||
maybe the setupfunc could be omitted?
|
||||
|
||||
optimizations
|
||||
---------------------------------------------------------------
|
||||
tags: 2.4 core
|
||||
|
||||
- look at ihook optimization such that all lookups for
|
||||
hooks relating to the same fspath are cached.
|
||||
|
||||
fix start/finish partial finailization problem
|
||||
---------------------------------------------------------------
|
||||
tags: bug core
|
||||
|
||||
if a configure/runtest_setup/sessionstart/... hook invocation partially
|
||||
fails the sessionfinishes is not called. Each hook implementation
|
||||
should better be repsonsible for registering a cleanup/finalizer
|
||||
appropriately to avoid this issue. Moreover/Alternatively, we could
|
||||
record which implementations of a hook succeeded and only call their
|
||||
teardown.
|
||||
|
||||
|
||||
relax requirement to have tests/testing contain an __init__
|
||||
----------------------------------------------------------------
|
||||
tags: feature
|
||||
bb: http://bitbucket.org/hpk42/py-trunk/issue/64
|
||||
|
||||
A local test run of a "tests" directory may work
|
||||
but a remote one fail because the tests directory
|
||||
does not contain an "__init__.py". Either give
|
||||
an error or make it work without the __init__.py
|
||||
i.e. port the nose-logic of unloading a test module.
|
||||
|
||||
customize test function collection
|
||||
-------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
- introduce pytest.mark.nocollect for not considering a function for
|
||||
test collection at all. maybe also introduce a pytest.mark.test to
|
||||
explicitly mark a function to become a tested one. Lookup JUnit ways
|
||||
of tagging tests.
|
||||
|
||||
introduce pytest.mark.importorskip
|
||||
-------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
in addition to the imperative pytest.importorskip also introduce
|
||||
a pytest.mark.importorskip so that the test count is more correct.
|
||||
|
||||
|
||||
introduce pytest.mark.platform
|
||||
-------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
Introduce nice-to-spell platform-skipping, examples:
|
||||
|
||||
@pytest.mark.platform("python3")
|
||||
@pytest.mark.platform("not python3")
|
||||
@pytest.mark.platform("win32 and not python3")
|
||||
@pytest.mark.platform("darwin")
|
||||
@pytest.mark.platform("not (jython and win32)")
|
||||
@pytest.mark.platform("not (jython and win32)", xfail=True)
|
||||
|
||||
etc. Idea is to allow Python expressions which can operate
|
||||
on common spellings for operating systems and python
|
||||
interpreter versions.
|
||||
|
||||
pytest.mark.xfail signature change
|
||||
-------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
change to pytest.mark.xfail(reason, (optional)condition)
|
||||
to better implement the word meaning. It also signals
|
||||
better that we always have some kind of an implementation
|
||||
reason that can be formualated.
|
||||
Compatibility? how to introduce a new name/keep compat?
|
||||
|
||||
allow to non-intrusively apply skipfs/xfail/marks
|
||||
---------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
use case: mark a module or directory structures
|
||||
to be skipped on certain platforms (i.e. no import
|
||||
attempt will be made).
|
||||
|
||||
consider introducing a hook/mechanism that allows to apply marks
|
||||
from conftests or plugins. (See extended parametrization)
|
||||
|
||||
|
||||
explicit referencing of conftest.py files
|
||||
-----------------------------------------
|
||||
tags: feature
|
||||
|
||||
allow to name conftest.py files (in sub directories) that should
|
||||
be imported early, as to include command line options.
|
||||
|
||||
improve central pytest ini file
|
||||
-------------------------------
|
||||
tags: feature
|
||||
|
||||
introduce more declarative configuration options:
|
||||
- (to-be-collected test directories)
|
||||
- required plugins
|
||||
- test func/class/file matching patterns
|
||||
- skip/xfail (non-intrusive)
|
||||
- pytest.ini and tox.ini and setup.cfg configuration in the same file
|
||||
|
||||
new documentation
|
||||
----------------------------------
|
||||
tags: feature
|
||||
|
||||
- logo pytest
|
||||
- examples for unittest or functional testing
|
||||
- resource management for functional testing
|
||||
- patterns: page object
|
||||
|
||||
have imported module mismatch honour relative paths
|
||||
--------------------------------------------------------
|
||||
tags: bug
|
||||
|
||||
With 1.1.1 pytest fails at least on windows if an import
|
||||
is relative and compared against an absolute conftest.py
|
||||
path. Normalize.
|
||||
|
||||
consider globals: pytest.ensuretemp and config
|
||||
--------------------------------------------------------------
|
||||
tags: experimental-wish
|
||||
|
||||
consider deprecating pytest.ensuretemp and pytest.config
|
||||
to further reduce pytest globality. Also consider
|
||||
having pytest.config and ensuretemp coming from
|
||||
a plugin rather than being there from the start.
|
||||
|
||||
|
||||
consider pytest_addsyspath hook
|
||||
-----------------------------------------
|
||||
tags: wish
|
||||
|
||||
pytest could call a new pytest_addsyspath() in order to systematically
|
||||
allow manipulation of sys.path and to inhibit it via --no-addsyspath
|
||||
in order to more easily run against installed packages.
|
||||
|
||||
Alternatively it could also be done via the config object
|
||||
and pytest_configure.
|
||||
|
||||
|
||||
|
||||
deprecate global pytest.config usage
|
||||
----------------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
pytest.ensuretemp and pytest.config are probably the last
|
||||
objects containing global state. Often using them is not
|
||||
necessary. This is about trying to get rid of them, i.e.
|
||||
deprecating them and checking with PyPy's usages as well
|
||||
as others.
|
||||
|
||||
remove deprecated bits in collect.py
|
||||
-------------------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
In an effort to further simplify code, review and remove deprecated bits
|
||||
in collect.py. Probably good:
|
||||
- inline consider_file/dir methods, no need to have them
|
||||
subclass-overridable because of hooks
|
||||
|
||||
implement fslayout decorator
|
||||
---------------------------------
|
||||
tags: feature
|
||||
|
||||
Improve the way how tests can work with pre-made examples,
|
||||
keeping the layout close to the test function:
|
||||
|
||||
@pytest.mark.fslayout("""
|
||||
conftest.py:
|
||||
# empty
|
||||
tests/
|
||||
test_%(NAME)s: # becomes test_run1.py
|
||||
def test_function(self):
|
||||
pass
|
||||
""")
|
||||
def test_run(pytester, fslayout):
|
||||
p = fslayout.findone("test_*.py")
|
||||
result = pytester.runpytest(p)
|
||||
assert result.ret == 0
|
||||
assert result.passed == 1
|
||||
|
||||
Another idea is to allow to define a full scenario including the run
|
||||
in one content string::
|
||||
|
||||
runscenario("""
|
||||
test_{TESTNAME}.py:
|
||||
import pytest
|
||||
@pytest.mark.xfail
|
||||
def test_that_fails():
|
||||
assert 0
|
||||
|
||||
@pytest.mark.skipif("True")
|
||||
def test_hello():
|
||||
pass
|
||||
|
||||
conftest.py:
|
||||
import pytest
|
||||
def pytest_runsetup_setup(item):
|
||||
pytest.skip("abc")
|
||||
|
||||
runpytest -rsxX
|
||||
*SKIP*{TESTNAME}*
|
||||
*1 skipped*
|
||||
""")
|
||||
|
||||
This could be run with at least three different ways to invoke pytest:
|
||||
through the shell, through "python -m pytest" and inlined. As inlined
|
||||
would be the fastest it could be run first (or "--fast" mode).
|
||||
|
||||
|
||||
Create isolate plugin
|
||||
---------------------
|
||||
tags: feature
|
||||
|
||||
The idea is that you can e.g. import modules in a test and afterwards
|
||||
sys.modules, sys.meta_path etc would be reverted. It can go further
|
||||
then just importing however, e.g. current working directory, file
|
||||
descriptors, ...
|
||||
|
||||
This would probably be done by marking::
|
||||
|
||||
@pytest.mark.isolate(importing=True, cwd=True, fds=False)
|
||||
def test_foo():
|
||||
...
|
||||
|
||||
With the possibility of doing this globally in an ini-file.
|
||||
|
||||
|
||||
fnmatch for test names
|
||||
----------------------
|
||||
tags: feature-wish
|
||||
|
||||
various testsuites use suffixes instead of prefixes for test classes
|
||||
also it lends itself to bdd style test names::
|
||||
|
||||
class UserBehaviour:
|
||||
def anonymous_should_not_have_inbox(user):
|
||||
...
|
||||
def registred_should_have_inbox(user):
|
||||
..
|
||||
|
||||
using the following in pytest.ini::
|
||||
|
||||
[pytest]
|
||||
python_classes = Test *Behaviour *Test
|
||||
python_functions = test *_should_*
|
||||
|
||||
|
||||
mechanism for running named parts of tests with different reporting behaviour
|
||||
------------------------------------------------------------------------------
|
||||
tags: feature-wish-incomplete
|
||||
|
||||
a few use-cases come to mind:
|
||||
|
||||
* fail assertions and record that without stopping a complete test
|
||||
|
||||
* this is in particular hepfull if a small bit of a test is known to fail/xfail::
|
||||
|
||||
def test_fun():
|
||||
with pytest.section('fdcheck, marks=pytest.mark.xfail_if(...)):
|
||||
breaks_on_windows()
|
||||
|
||||
* divide functional/acceptance tests into sections
|
||||
* provide a different mechanism for generators, maybe something like::
|
||||
|
||||
def pytest_runtest_call(item)
|
||||
if not generator:
|
||||
...
|
||||
prepare_check = GeneratorCheckprepare()
|
||||
|
||||
gen = item.obj(**fixtures)
|
||||
for check in gen
|
||||
id, call = prepare_check(check)
|
||||
# bubble should only prevent exception propagation after a failure
|
||||
# the whole test should still fail
|
||||
# there might be need for a lower level api and taking custom markers into account
|
||||
with pytest.section(id, bubble=False):
|
||||
call()
|
||||
|
||||
|
|
@ -4,6 +4,7 @@ include AUTHORS
|
|||
|
||||
include README.rst
|
||||
include CONTRIBUTING.rst
|
||||
include HOWTORELEASE.rst
|
||||
|
||||
include tox.ini
|
||||
include setup.py
|
||||
|
@ -29,6 +30,3 @@ recursive-exclude * *.pyc *.pyo
|
|||
exclude appveyor/install.ps1
|
||||
exclude appveyor.yml
|
||||
exclude appveyor
|
||||
|
||||
exclude ISSUES.txt
|
||||
exclude HOWTORELEASE.rst
|
||||
|
|
|
@ -687,7 +687,7 @@ class Session(FSCollector):
|
|||
# This method is sometimes invoked when AssertionRewritingHook, which
|
||||
# does not define a get_filename method, is already in place:
|
||||
try:
|
||||
path = loader.get_filename()
|
||||
path = loader.get_filename(x)
|
||||
except AttributeError:
|
||||
# Retrieve path from AssertionRewritingHook:
|
||||
path = loader.modules[x][0].co_filename
|
||||
|
|
|
@ -283,6 +283,21 @@ class MarkDecorator:
|
|||
return self.__class__(self.name, args=args, kwargs=kw)
|
||||
|
||||
|
||||
def extract_argvalue(maybe_marked_args):
|
||||
# TODO: incorrect mark data, the old code wanst able to collect lists
|
||||
# individual parametrized argument sets can be wrapped in a series
|
||||
# of markers in which case we unwrap the values and apply the mark
|
||||
# at Function init
|
||||
newmarks = {}
|
||||
argval = maybe_marked_args
|
||||
while isinstance(argval, MarkDecorator):
|
||||
newmark = MarkDecorator(argval.markname,
|
||||
argval.args[:-1], argval.kwargs)
|
||||
newmarks[newmark.markname] = newmark
|
||||
argval = argval.args[-1]
|
||||
return argval, newmarks
|
||||
|
||||
|
||||
class MarkInfo:
|
||||
""" Marking object created by :class:`MarkDecorator` instances. """
|
||||
def __init__(self, name, args, kwargs):
|
||||
|
|
|
@ -5,10 +5,11 @@ import inspect
|
|||
import sys
|
||||
import collections
|
||||
import math
|
||||
from itertools import count
|
||||
|
||||
import py
|
||||
import pytest
|
||||
from _pytest.mark import MarkDecorator, MarkerError
|
||||
from _pytest.mark import MarkerError
|
||||
|
||||
|
||||
import _pytest
|
||||
|
@ -431,10 +432,12 @@ class Module(pytest.File, PyCollector):
|
|||
"Make sure your test modules/packages have valid Python names."
|
||||
% (self.fspath, exc or exc_class)
|
||||
)
|
||||
except _pytest.runner.Skipped:
|
||||
except _pytest.runner.Skipped as e:
|
||||
if e.allow_module_level:
|
||||
raise
|
||||
raise self.CollectError(
|
||||
"Using @pytest.skip outside a test (e.g. as a test function "
|
||||
"decorator) is not allowed. Use @pytest.mark.skip or "
|
||||
"Using @pytest.skip outside of a test (e.g. as a test "
|
||||
"function decorator) is not allowed. Use @pytest.mark.skip or "
|
||||
"@pytest.mark.skipif instead."
|
||||
)
|
||||
self.config.pluginmanager.consider_module(mod)
|
||||
|
@ -774,19 +777,14 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
to set a dynamic scope using test context or configuration.
|
||||
"""
|
||||
from _pytest.fixtures import scopes
|
||||
# individual parametrized argument sets can be wrapped in a series
|
||||
# of markers in which case we unwrap the values and apply the mark
|
||||
# at Function init
|
||||
newkeywords = {}
|
||||
from _pytest.mark import extract_argvalue
|
||||
|
||||
unwrapped_argvalues = []
|
||||
for i, argval in enumerate(argvalues):
|
||||
while isinstance(argval, MarkDecorator):
|
||||
newmark = MarkDecorator(argval.markname,
|
||||
argval.args[:-1], argval.kwargs)
|
||||
newmarks = newkeywords.setdefault(i, {})
|
||||
newmarks[newmark.markname] = newmark
|
||||
argval = argval.args[-1]
|
||||
newkeywords = []
|
||||
for maybe_marked_args in argvalues:
|
||||
argval, newmarks = extract_argvalue(maybe_marked_args)
|
||||
unwrapped_argvalues.append(argval)
|
||||
newkeywords.append(newmarks)
|
||||
argvalues = unwrapped_argvalues
|
||||
|
||||
if not isinstance(argnames, (tuple, list)):
|
||||
|
@ -801,18 +799,11 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
newmark = pytest.mark.skip(
|
||||
reason="got empty parameter set %r, function %s at %s:%d" % (
|
||||
argnames, self.function.__name__, fs, lineno))
|
||||
newmarks = newkeywords.setdefault(0, {})
|
||||
newmarks[newmark.markname] = newmark
|
||||
newkeywords = [{newmark.markname: newmark}]
|
||||
|
||||
if scope is None:
|
||||
if self._arg2fixturedefs:
|
||||
# Takes the most narrow scope from used fixtures
|
||||
fixtures_scopes = [fixturedef[0].scope for fixturedef in self._arg2fixturedefs.values()]
|
||||
for scope in reversed(scopes):
|
||||
if scope in fixtures_scopes:
|
||||
break
|
||||
else:
|
||||
scope = 'function'
|
||||
scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
|
||||
|
||||
scopenum = scopes.index(scope)
|
||||
valtypes = {}
|
||||
for arg in argnames:
|
||||
|
@ -846,12 +837,12 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
ids = idmaker(argnames, argvalues, idfn, ids, self.config)
|
||||
newcalls = []
|
||||
for callspec in self._calls or [CallSpec2(self)]:
|
||||
for param_index, valset in enumerate(argvalues):
|
||||
elements = zip(ids, argvalues, newkeywords, count())
|
||||
for a_id, valset, keywords, param_index in elements:
|
||||
assert len(valset) == len(argnames)
|
||||
newcallspec = callspec.copy(self)
|
||||
newcallspec.setmulti(valtypes, argnames, valset, ids[param_index],
|
||||
newkeywords.get(param_index, {}), scopenum,
|
||||
param_index)
|
||||
newcallspec.setmulti(valtypes, argnames, valset, a_id,
|
||||
keywords, scopenum, param_index)
|
||||
newcalls.append(newcallspec)
|
||||
self._calls = newcalls
|
||||
|
||||
|
@ -892,6 +883,30 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
|||
self._calls.append(cs)
|
||||
|
||||
|
||||
def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
|
||||
"""Find the most appropriate scope for a parametrized call based on its arguments.
|
||||
|
||||
When there's at least one direct argument, always use "function" scope.
|
||||
|
||||
When a test function is parametrized and all its arguments are indirect
|
||||
(e.g. fixtures), return the most narrow scope based on the fixtures used.
|
||||
|
||||
Related to issue #1832, based on code posted by @Kingdread.
|
||||
"""
|
||||
from _pytest.fixtures import scopes
|
||||
indirect_as_list = isinstance(indirect, (list, tuple))
|
||||
all_arguments_are_fixtures = indirect is True or \
|
||||
indirect_as_list and len(indirect) == argnames
|
||||
if all_arguments_are_fixtures:
|
||||
fixturedefs = arg2fixturedefs or {}
|
||||
used_scopes = [fixturedef[0].scope for name, fixturedef in fixturedefs.items()]
|
||||
if used_scopes:
|
||||
# Takes the most narrow scope from used fixtures
|
||||
for scope in reversed(scopes):
|
||||
if scope in used_scopes:
|
||||
return scope
|
||||
|
||||
return 'function'
|
||||
|
||||
|
||||
def _idval(val, argname, idx, idfn, config=None):
|
||||
|
@ -921,7 +936,7 @@ def _idval(val, argname, idx, idfn, config=None):
|
|||
return str(argname)+str(idx)
|
||||
|
||||
def _idvalset(idx, valset, argnames, idfn, ids, config=None):
|
||||
if ids is None or ids[idx] is None:
|
||||
if ids is None or (idx >= len(ids) or ids[idx] is None):
|
||||
this_id = [_idval(val, argname, idx, idfn, config)
|
||||
for val, argname in zip(valset, argnames)]
|
||||
return "-".join(this_id)
|
||||
|
|
|
@ -492,10 +492,16 @@ class Skipped(OutcomeException):
|
|||
# in order to have Skipped exception printing shorter/nicer
|
||||
__module__ = 'builtins'
|
||||
|
||||
def __init__(self, msg=None, pytrace=True, allow_module_level=False):
|
||||
OutcomeException.__init__(self, msg=msg, pytrace=pytrace)
|
||||
self.allow_module_level = allow_module_level
|
||||
|
||||
|
||||
class Failed(OutcomeException):
|
||||
""" raised from an explicit call to pytest.fail() """
|
||||
__module__ = 'builtins'
|
||||
|
||||
|
||||
class Exit(KeyboardInterrupt):
|
||||
""" raised for immediate program exits (no tracebacks/summaries)"""
|
||||
def __init__(self, msg="unknown reason"):
|
||||
|
@ -546,7 +552,7 @@ def importorskip(modname, minversion=None):
|
|||
# Do not raise chained exception here(#1485)
|
||||
should_skip = True
|
||||
if should_skip:
|
||||
skip("could not import %r" %(modname,))
|
||||
raise Skipped("could not import %r" %(modname,), allow_module_level=True)
|
||||
mod = sys.modules[modname]
|
||||
if minversion is None:
|
||||
return mod
|
||||
|
@ -555,10 +561,11 @@ def importorskip(modname, minversion=None):
|
|||
try:
|
||||
from pkg_resources import parse_version as pv
|
||||
except ImportError:
|
||||
skip("we have a required version for %r but can not import "
|
||||
"no pkg_resources to parse version strings." %(modname,))
|
||||
raise Skipped("we have a required version for %r but can not import "
|
||||
"pkg_resources to parse version strings." % (modname,),
|
||||
allow_module_level=True)
|
||||
if verattr is None or pv(verattr) < pv(minversion):
|
||||
skip("module %r has __version__ %r, required is: %r" %(
|
||||
modname, verattr, minversion))
|
||||
raise Skipped("module %r has __version__ %r, required is: %r" %(
|
||||
modname, verattr, minversion), allow_module_level=True)
|
||||
return mod
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ Release announcements
|
|||
|
||||
|
||||
sprint2016
|
||||
release-3.0.1
|
||||
release-3.0.0
|
||||
release-2.9.2
|
||||
release-2.9.1
|
||||
release-2.9.0
|
||||
|
|
|
@ -41,7 +41,7 @@ Changes 2.6.3
|
|||
dep). Thanks Charles Cloud for analysing the issue.
|
||||
|
||||
- fix conftest related fixture visibility issue: when running with a
|
||||
CWD outside a test package pytest would get fixture discovery wrong.
|
||||
CWD outside of a test package pytest would get fixture discovery wrong.
|
||||
Thanks to Wolfgang Schnerring for figuring out a reproducable example.
|
||||
|
||||
- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
|
||||
|
|
|
@ -6,7 +6,7 @@ The pytest team is proud to announce the 3.0.0 release!
|
|||
pytest is a mature Python testing tool with more than a 1600 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
This release contains a lot of bugs and improvements, and much of
|
||||
This release contains a lot of bugs fixes and improvements, and much of
|
||||
the work done on it was possible because of the 2016 Sprint[1], which
|
||||
was funded by an indiegogo campaign which raised over US$12,000 with
|
||||
nearly 100 backers.
|
||||
|
@ -76,7 +76,7 @@ Thanks to all who contributed to this release, among them:
|
|||
|
||||
|
||||
Happy testing,
|
||||
The py.test Development Team
|
||||
The Pytest Development Team
|
||||
|
||||
[1] http://blog.pytest.org/2016/pytest-development-sprint/
|
||||
[2] http://blog.pytest.org/2016/whats-new-in-pytest-30/
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
pytest-3.0.1
|
||||
============
|
||||
|
||||
pytest 3.0.1 has just been released to PyPI.
|
||||
|
||||
This release fixes some regressions reported in version 3.0.0, being a
|
||||
drop-in replacement. To upgrade:
|
||||
|
||||
pip install --upgrade pytest
|
||||
|
||||
The changelog is available at http://doc.pytest.org/en/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
Adam Chainz
|
||||
Andrew Svetlov
|
||||
Bruno Oliveira
|
||||
Daniel Hahler
|
||||
Dmitry Dygalo
|
||||
Florian Bruhin
|
||||
Marcin Bachry
|
||||
Ronny Pfannschmidt
|
||||
matthiasha
|
||||
|
||||
Happy testing,
|
||||
The py.test Development Team
|
|
@ -26,7 +26,7 @@ you will see the return value of the function call::
|
|||
|
||||
$ pytest test_assert1.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
|
||||
|
@ -170,7 +170,7 @@ if you run this module::
|
|||
|
||||
$ pytest test_assert2.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ If you then run it with ``--lf``::
|
|||
|
||||
$ pytest --lf
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
run-last-failure: rerun last 2 failures
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 50 items
|
||||
|
@ -122,7 +122,7 @@ of ``FF`` and dots)::
|
|||
|
||||
$ pytest --ff
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
run-last-failure: rerun last 2 failures first
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 50 items
|
||||
|
@ -227,7 +227,7 @@ You can always peek at the content of the cache using the
|
|||
|
||||
$ py.test --cache-show
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
cachedir: $REGENDOC_TMPDIR/.cache
|
||||
------------------------------- cache values -------------------------------
|
||||
|
|
|
@ -64,7 +64,7 @@ of the failing function and hide the other one::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ then you can just invoke ``pytest`` without command line options::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||
collected 1 items
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[pytest]
|
||||
testfilepatterns =
|
||||
${topdir}/tests/unit/test_${basename}
|
||||
${topdir}/tests/functional/*.py
|
|
@ -31,7 +31,7 @@ You can then restrict a test run to only run tests marked with ``webtest``::
|
|||
|
||||
$ pytest -v -m webtest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
@ -45,7 +45,7 @@ Or the inverse, running all tests except the webtest ones::
|
|||
|
||||
$ pytest -v -m "not webtest"
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
@ -66,7 +66,7 @@ tests based on their module, class, method, or function name::
|
|||
|
||||
$ pytest -v test_server.py::TestClass::test_method
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 5 items
|
||||
|
@ -79,7 +79,7 @@ You can also select on the class::
|
|||
|
||||
$ pytest -v test_server.py::TestClass
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
@ -92,7 +92,7 @@ Or select multiple nodes::
|
|||
|
||||
$ pytest -v test_server.py::TestClass test_server.py::test_send_http
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 8 items
|
||||
|
@ -130,7 +130,7 @@ select tests based on their names::
|
|||
|
||||
$ pytest -v -k http # running with the above defined example module
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
@ -144,7 +144,7 @@ And you can also run all tests except the ones that match the keyword::
|
|||
|
||||
$ pytest -k "not send_http" -v
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
@ -160,7 +160,7 @@ Or to select "http" and "quick" tests::
|
|||
|
||||
$ pytest -k "http or quick" -v
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
@ -352,7 +352,7 @@ the test needs::
|
|||
|
||||
$ pytest -E stage2
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
|
||||
|
@ -364,7 +364,7 @@ and here is one that specifies exactly the environment needed::
|
|||
|
||||
$ pytest -E stage1
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
|
||||
|
@ -485,7 +485,7 @@ then you will see two test skipped and two executed tests as expected::
|
|||
|
||||
$ pytest -rs # this option reports skip reasons
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 4 items
|
||||
|
||||
|
@ -499,7 +499,7 @@ Note that if you specify a platform via the marker-command line option like this
|
|||
|
||||
$ pytest -m linux2
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 4 items
|
||||
|
||||
|
@ -551,7 +551,7 @@ We can now use the ``-m option`` to select one set::
|
|||
|
||||
$ pytest -m interface --tb=short
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 4 items
|
||||
|
||||
|
@ -573,7 +573,7 @@ or to select both "event" and "interface" tests::
|
|||
|
||||
$ pytest -m "interface or event" --tb=short
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 4 items
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ now execute the test specification::
|
|||
|
||||
nonpython $ pytest test_simple.yml
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
@ -59,7 +59,7 @@ consulted when reporting in ``verbose`` mode::
|
|||
|
||||
nonpython $ pytest -v
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||
collecting ... collected 2 items
|
||||
|
@ -81,7 +81,7 @@ interesting to just look at the collection tree::
|
|||
|
||||
nonpython $ pytest --collect-only
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||
collected 2 items
|
||||
<YamlFile 'test_simple.yml'>
|
||||
|
|
|
@ -130,7 +130,7 @@ objects, they are still using the default pytest representation::
|
|||
|
||||
$ pytest test_time.py --collect-only
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 6 items
|
||||
<Module 'test_time.py'>
|
||||
|
@ -181,7 +181,7 @@ this is a fully self-contained example which you can run with::
|
|||
|
||||
$ pytest test_scenarios.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 4 items
|
||||
|
||||
|
@ -194,7 +194,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
|
|||
|
||||
$ pytest --collect-only test_scenarios.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 4 items
|
||||
<Module 'test_scenarios.py'>
|
||||
|
@ -259,7 +259,7 @@ Let's first see how it looks like at collection time::
|
|||
|
||||
$ pytest test_backends.py --collect-only
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
<Module 'test_backends.py'>
|
||||
|
@ -320,7 +320,7 @@ The result of this test will be successful::
|
|||
|
||||
$ pytest test_indirect_list.py --collect-only
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
<Module 'test_indirect_list.py'>
|
||||
|
@ -447,7 +447,7 @@ If you run this with reporting for skips enabled::
|
|||
|
||||
$ pytest -rs test_module.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ then the test collection looks like this::
|
|||
|
||||
$ pytest --collect-only
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||
collected 2 items
|
||||
<Module 'check_myapp.py'>
|
||||
|
@ -163,7 +163,7 @@ You can always peek at the collection tree without running tests like this::
|
|||
|
||||
. $ pytest --collect-only pythoncollection.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||
collected 3 items
|
||||
<Module 'CWD/pythoncollection.py'>
|
||||
|
@ -230,7 +230,7 @@ will be left out::
|
|||
|
||||
$ pytest --collect-only
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||
collected 0 items
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ get on the terminal - we are working on that):
|
|||
|
||||
assertion $ pytest failure_demo.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR/assertion, inifile:
|
||||
collected 42 items
|
||||
|
||||
|
@ -361,7 +361,7 @@ get on the terminal - we are working on that):
|
|||
> int(s)
|
||||
E ValueError: invalid literal for int() with base 10: 'qwe'
|
||||
|
||||
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python.py:1174>:1: ValueError
|
||||
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python.py:1189>:1: ValueError
|
||||
_______ TestRaises.test_raises_doesnt ________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||
|
|
|
@ -108,7 +108,7 @@ directory with the above conftest.py::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 0 items
|
||||
|
||||
|
@ -156,7 +156,7 @@ and when running it will see a skipped "slow" test::
|
|||
|
||||
$ pytest -rs # "-rs" means report details on the little 's'
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
@ -170,7 +170,7 @@ Or run it including the ``slow`` marked test::
|
|||
|
||||
$ pytest --runslow
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
@ -284,7 +284,7 @@ which will add the string to the test header accordingly::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
project deps: mylib-1.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 0 items
|
||||
|
@ -308,7 +308,7 @@ which will add info only when run with "--v"::
|
|||
|
||||
$ pytest -v
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
info1: did you know that ...
|
||||
did you?
|
||||
|
@ -321,7 +321,7 @@ and nothing when run plainly::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 0 items
|
||||
|
||||
|
@ -354,7 +354,7 @@ Now we can profile which test functions execute the slowest::
|
|||
|
||||
$ pytest --durations=3
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 3 items
|
||||
|
||||
|
@ -416,7 +416,7 @@ If we run this::
|
|||
|
||||
$ pytest -rx
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 4 items
|
||||
|
||||
|
@ -487,7 +487,7 @@ We can run this::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 7 items
|
||||
|
||||
|
@ -591,7 +591,7 @@ and run them::
|
|||
|
||||
$ pytest test_module.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
@ -681,7 +681,7 @@ and run it::
|
|||
|
||||
$ pytest -s test_module.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 3 items
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
|
|||
|
||||
$ pytest test_smtpsimple.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
|
||||
|
@ -188,7 +188,7 @@ inspect what is going on and can now run the tests::
|
|||
|
||||
$ pytest test_module.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
@ -516,7 +516,7 @@ Running the above tests results in the following test IDs being used::
|
|||
|
||||
$ pytest --collect-only
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 11 items
|
||||
<Module 'test_anothersmtp.py'>
|
||||
|
@ -569,7 +569,7 @@ Here we declare an ``app`` fixture which receives the previously defined
|
|||
|
||||
$ pytest -v test_appsetup.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 2 items
|
||||
|
@ -638,7 +638,7 @@ Let's run the tests in verbose mode and with looking at the print-output::
|
|||
|
||||
$ pytest -v -s test_module.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 8 items
|
||||
|
|
|
@ -27,7 +27,7 @@ Installation options::
|
|||
To check your installation has installed the correct version::
|
||||
|
||||
$ pytest --version
|
||||
This is pytest version 3.0.0, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py
|
||||
This is pytest version 3.0.1, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py
|
||||
|
||||
If you get an error checkout :ref:`installation issues`.
|
||||
|
||||
|
@ -49,7 +49,7 @@ That's it. You can execute the test function now::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ them in turn::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 3 items
|
||||
|
||||
|
@ -103,7 +103,7 @@ Let's run this::
|
|||
|
||||
$ pytest
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 3 items
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ Running it with the report-on-xfail option gives this output::
|
|||
|
||||
example $ pytest -rx xfail_demo.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR/example, inifile:
|
||||
collected 7 items
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ Running this would result in a passed test except for the last
|
|||
|
||||
$ pytest test_tmpdir.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 items
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ the ``self.db`` values in the traceback::
|
|||
|
||||
$ pytest test_unittest_db.py
|
||||
======= test session starts ========
|
||||
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
|
||||
platform linux -- Python 3.5.2, pytest-3.0.1, py-1.4.31, pluggy-0.3.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
|
|
@ -293,7 +293,7 @@ can use like this::
|
|||
pass
|
||||
""")
|
||||
result = testdir.runpytest("--verbose")
|
||||
result.fnmatch_lines("""
|
||||
result.stdout.fnmatch_lines("""
|
||||
test_example*
|
||||
""")
|
||||
|
||||
|
|
|
@ -763,3 +763,21 @@ class TestDurationWithFixture:
|
|||
* call *test_1*
|
||||
""")
|
||||
|
||||
|
||||
def test_zipimport_hook(testdir, tmpdir):
|
||||
"""Test package loader is being used correctly (see #1837)."""
|
||||
zipapp = pytest.importorskip('zipapp')
|
||||
testdir.tmpdir.join('app').ensure(dir=1)
|
||||
testdir.makepyfile(**{
|
||||
'app/foo.py': """
|
||||
import pytest
|
||||
def main():
|
||||
pytest.main(['--pyarg', 'foo'])
|
||||
""",
|
||||
})
|
||||
target = tmpdir.join('foo.zip')
|
||||
zipapp.create_archive(str(testdir.tmpdir.join('app')), str(target), main='foo:main')
|
||||
result = testdir.runpython(target)
|
||||
assert result.ret == 0
|
||||
result.stderr.fnmatch_lines(['*not found*foo*'])
|
||||
assert 'INTERNALERROR>' not in result.stdout.str()
|
||||
|
|
|
@ -889,6 +889,33 @@ class TestMetafuncFunctional:
|
|||
"*test_function*advanced*FAILED",
|
||||
])
|
||||
|
||||
def test_fixture_parametrized_empty_ids(self, testdir):
|
||||
"""Fixtures parametrized with empty ids cause an internal error (#1849)."""
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="module", ids=[], params=[])
|
||||
def temp(request):
|
||||
return request.param
|
||||
|
||||
def test_temp(temp):
|
||||
pass
|
||||
''')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 1 skipped *'])
|
||||
|
||||
def test_parametrized_empty_ids(self, testdir):
|
||||
"""Tests parametrized with empty ids cause an internal error (#1849)."""
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.mark.parametrize('temp', [], ids=list())
|
||||
def test_temp(temp):
|
||||
pass
|
||||
''')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 1 skipped *'])
|
||||
|
||||
def test_parametrize_with_identical_ids_get_unique_names(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -930,43 +957,6 @@ class TestMetafuncFunctional:
|
|||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=5)
|
||||
|
||||
def test_parametrize_issue634(self, testdir):
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def foo(request):
|
||||
print('preparing foo-%d' % request.param)
|
||||
return 'foo-%d' % request.param
|
||||
|
||||
|
||||
def test_one(foo):
|
||||
pass
|
||||
|
||||
|
||||
def test_two(foo):
|
||||
pass
|
||||
|
||||
|
||||
test_two.test_with = (2, 3)
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
params = (1, 2, 3, 4)
|
||||
if not 'foo' in metafunc.fixturenames:
|
||||
return
|
||||
|
||||
test_with = getattr(metafunc.function, 'test_with', None)
|
||||
if test_with:
|
||||
params = test_with
|
||||
metafunc.parametrize('foo', params, indirect=True)
|
||||
|
||||
''')
|
||||
result = testdir.runpytest("-s")
|
||||
output = result.stdout.str()
|
||||
assert output.count('preparing foo-2') == 1
|
||||
assert output.count('preparing foo-3') == 1
|
||||
|
||||
def test_parametrize_issue323(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -1047,6 +1037,125 @@ class TestMetafuncFunctional:
|
|||
assert expectederror in failures[0].longrepr.reprcrash.message
|
||||
|
||||
|
||||
class TestMetafuncFunctionalAuto:
|
||||
"""
|
||||
Tests related to automatically find out the correct scope for parametrized tests (#1832).
|
||||
"""
|
||||
|
||||
def test_parametrize_auto_scope(self, testdir):
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
def fixture():
|
||||
return 1
|
||||
|
||||
@pytest.mark.parametrize('animal', ["dog", "cat"])
|
||||
def test_1(animal):
|
||||
assert animal in ('dog', 'cat')
|
||||
|
||||
@pytest.mark.parametrize('animal', ['fish'])
|
||||
def test_2(animal):
|
||||
assert animal == 'fish'
|
||||
|
||||
''')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 3 passed *'])
|
||||
|
||||
def test_parametrize_auto_scope_indirect(self, testdir):
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def echo(request):
|
||||
return request.param
|
||||
|
||||
@pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=['echo'])
|
||||
def test_1(animal, echo):
|
||||
assert animal in ('dog', 'cat')
|
||||
assert echo in (1, 2, 3)
|
||||
|
||||
@pytest.mark.parametrize('animal, echo', [('fish', 3)], indirect=['echo'])
|
||||
def test_2(animal, echo):
|
||||
assert animal == 'fish'
|
||||
assert echo in (1, 2, 3)
|
||||
''')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 3 passed *'])
|
||||
|
||||
def test_parametrize_auto_scope_override_fixture(self, testdir):
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
def animal():
|
||||
return 'fox'
|
||||
|
||||
@pytest.mark.parametrize('animal', ["dog", "cat"])
|
||||
def test_1(animal):
|
||||
assert animal in ('dog', 'cat')
|
||||
''')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 2 passed *'])
|
||||
|
||||
def test_parametrize_all_indirects(self, testdir):
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.fixture()
|
||||
def animal(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def echo(request):
|
||||
return request.param
|
||||
|
||||
@pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=True)
|
||||
def test_1(animal, echo):
|
||||
assert animal in ('dog', 'cat')
|
||||
assert echo in (1, 2, 3)
|
||||
|
||||
@pytest.mark.parametrize('animal, echo', [("fish", 3)], indirect=True)
|
||||
def test_2(animal, echo):
|
||||
assert animal == 'fish'
|
||||
assert echo in (1, 2, 3)
|
||||
''')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 3 passed *'])
|
||||
|
||||
def test_parametrize_issue634(self, testdir):
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def foo(request):
|
||||
print('preparing foo-%d' % request.param)
|
||||
return 'foo-%d' % request.param
|
||||
|
||||
def test_one(foo):
|
||||
pass
|
||||
|
||||
def test_two(foo):
|
||||
pass
|
||||
|
||||
test_two.test_with = (2, 3)
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
params = (1, 2, 3, 4)
|
||||
if not 'foo' in metafunc.fixturenames:
|
||||
return
|
||||
|
||||
test_with = getattr(metafunc.function, 'test_with', None)
|
||||
if test_with:
|
||||
params = test_with
|
||||
metafunc.parametrize('foo', params, indirect=True)
|
||||
''')
|
||||
result = testdir.runpytest("-s")
|
||||
output = result.stdout.str()
|
||||
assert output.count('preparing foo-2') == 1
|
||||
assert output.count('preparing foo-3') == 1
|
||||
|
||||
|
||||
class TestMarkersWithParametrization:
|
||||
pytestmark = pytest.mark.issue308
|
||||
def test_simple_mark(self, testdir):
|
||||
|
|
|
@ -571,6 +571,19 @@ def test_importorskip_dev_module(monkeypatch):
|
|||
pytest.fail("spurious skip")
|
||||
|
||||
|
||||
def test_importorskip_module_level(testdir):
|
||||
"""importorskip must be able to skip entire modules when used at module level"""
|
||||
testdir.makepyfile('''
|
||||
import pytest
|
||||
foobarbaz = pytest.importorskip("foobarbaz")
|
||||
|
||||
def test_foo():
|
||||
pass
|
||||
''')
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['*collected 0 items / 1 skipped*'])
|
||||
|
||||
|
||||
def test_pytest_cmdline_main(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
import pytest
|
||||
|
|
|
@ -967,5 +967,5 @@ def test_module_level_skip_error(testdir):
|
|||
""")
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(
|
||||
"*Using @pytest.skip outside a test * is not allowed*"
|
||||
"*Using @pytest.skip outside of a test * is not allowed*"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue