Compare commits

...

394 Commits
3.0.0 ... 3.0.7

Author SHA1 Message Date
Bruno Oliveira
90c934e25e Include release 3.0.7 announce in index.rst 2017-03-13 18:59:15 -04:00
Bruno Oliveira
d58780f9a6 Update regendoc 2017-03-13 18:41:20 -04:00
Bruno Oliveira
b1ab2ca963 Bump to version 3.0.7 and update CHANGELOG 2017-03-13 18:37:49 -04:00
Ronny Pfannschmidt
906b40fbb2 Merge pull request #2289 from fbjorn/fix-trailing-whitespace-in-terminal
Fix trailing whitespace in terminal output
2017-03-05 22:45:46 +01:00
fbjorn
cee578e327 Fix trailing whitespace in terminal output 2017-03-05 23:20:55 +03:00
Florian Bruhin
29383d477d Merge pull request #2288 from nodakai/patch-1
assert.rst: typographical correction
2017-03-05 18:37:07 +01:00
NODA, Kai
e05ff0338a assert.rst: typographical correction 2017-03-06 01:01:55 +08:00
Floris Bruynooghe
b28749eb92 Merge pull request #2284 from omerhadari/bugfix-unprintable-assertion-errors
Bugfix unprintable assertion errors
2017-03-04 15:28:11 +00:00
Ronny Pfannschmidt
07623e78ce Merge pull request #2286 from pytest-dev/disable-py37-travis
Allow py37-nightly to fail on Travis
2017-03-04 11:55:07 +01:00
Omer Hadari
dd25ae7f33 added in the correct alphabitcal order 2017-03-04 12:50:02 +02:00
Omer Hadari
02dc545311 added in the correct alphabitcal order 2017-03-04 12:49:00 +02:00
Bruno Oliveira
b61dcded37 Allow py37-nightly to fail on Travis
Related to #2285
2017-03-04 07:17:39 -03:00
Omer Hadari
f71467f5b1 added link to changelog 2017-03-04 10:55:59 +02:00
Omer Hadari
6aaf7ae18b added to authors and changelog 2017-03-04 10:32:14 +02:00
Omer Hadari
6a52fe1650 fixed internal error on unprintable raised AssertionErrors 2017-03-04 10:26:46 +02:00
Bruno Oliveira
5721d8aed1 Merge pull request #2249 from pfhayes/anydbmfix
Fix importing anydbm within pytest
2017-03-01 14:41:31 -03:00
Bruno Oliveira
3aac3d0a00 Merge branch 'master' into anydbmfix 2017-03-01 14:41:18 -03:00
Floris Bruynooghe
3e3f20380e Merge pull request #2277 from nicoddemus/yield-fixture-docs-2262
Improve docs for yield-fixture and with statement a bit
2017-03-01 11:32:18 -03:00
Bruno Oliveira
bb5f200ed7 Improve docs for yield-fixture and with statement a bit
Fix #2262
2017-02-25 12:06:51 -03:00
Ronny Pfannschmidt
0a89db2739 Merge pull request #2271 from KKoukiou/double-tag
junitxml: Fix double system-out tags per testcase
2017-02-22 18:20:17 +01:00
Katerina Koukiou
d3a6be4130 junitxml: Fix double system-out tags per testcase
In the xml report we now have two occurences for the system-out tag if
the testcase writes to stdout both on call and teardown and fails in
teardown.
This behaviour is against the xsd.
This patch makes sure that the system-out section exists only
once per testcase.
2017-02-22 16:39:20 +01:00
Bruno Oliveira
6680cb9100 Merge pull request #2264 from asottile/simplify_travis
Simplify travis.yml with tox environment variables
2017-02-19 18:07:13 -03:00
Anthony Sottile
5fd010c4c3 Simplify travis.yml with tox environment variables 2017-02-19 09:02:35 -08:00
Bruno Oliveira
21a09f0895 Merge pull request #2261 from vmuriart/doc-report_header
Document pytest_report_header and conftest behavior
2017-02-17 12:22:28 -02:00
Victor Uriarte
a88017cf26 Add note documenting #2257 2017-02-16 23:00:55 -07:00
Victor Uriarte
58d7f4e048 Correct typo 2017-02-16 22:52:06 -07:00
Bruno Oliveira
9c809f5ad0 Merge pull request #2255 from scop/spelling
Spelling fixes
2017-02-15 18:41:49 -02:00
Bruno Oliveira
27f12ed0c3 Merge pull request #2254 from scop/py36-escseq
Python 3.6 invalid escape sequence deprecation fixes
2017-02-15 18:41:06 -02:00
Ronny Pfannschmidt
0a26132232 Merge pull request #2241 from nicoddemus/override-python-files
--override-ini now correctly overrides some fundamental options like "python_files"
2017-02-15 21:40:50 +01:00
Bruno Oliveira
8f98ac5ae8 Fix typo in docs "textures" -> "fixtures" 2017-02-15 13:15:53 -02:00
Ville Skyttä
ede4e9171f Spelling fixes 2017-02-15 17:00:58 +02:00
Ville Skyttä
eeb6603d71 Python 3.6 invalid escape sequence deprecation fixes 2017-02-15 16:54:53 +02:00
Ronny Pfannschmidt
231e2f9a90 Merge pull request #2252 from nicoddemus/fixture-visibility-docs
Improve pytest_plugins docs
2017-02-15 15:53:30 +01:00
Bruno Oliveira
c4d974460c Improve pytest_plugins docs
As discussed in #2246
2017-02-15 11:57:03 -02:00
Patrick Hayes
6b5566db66 Update changelog 2017-02-14 17:47:42 -08:00
Patrick Hayes
49289fed52 Fix docs 2017-02-14 17:21:20 -08:00
Patrick Hayes
00ec30353b Update docs as requested 2017-02-14 17:08:42 -08:00
Patrick Hayes
58ce3a9e8c Safer sys.modules delete 2017-02-14 16:54:32 -08:00
Floris Bruynooghe
427bf42a52 Merge pull request #2247 from flub/flub/training
Mention next training event.
2017-02-14 12:06:13 +00:00
Floris Bruynooghe
b536fb7ace Mention next training event. 2017-02-14 11:45:39 +00:00
Bruno Oliveira
9eb1d73951 --override-ini now correctly overrides some fundamental options like "python_files"
#2238
2017-02-08 23:03:33 -02:00
Bruno Oliveira
3d9c5cf19f Merge pull request #2225 from mbyt/allow_skipping_unittests_with_pdb_active
Allow to skip unittests if --pdb active
2017-02-08 21:23:51 -02:00
Bruno Oliveira
6a097aa0f1 Merge branch 'master' into allow_skipping_unittests_with_pdb_active 2017-02-08 20:30:14 -02:00
Bruno Oliveira
a4fb971c1f Merge pull request #2235 from bluetech/dont-execute-properties
ignore property errors when parsing fixure factories
2017-02-07 23:41:36 -02:00
Ran Benita
3a0a0c2df9 Ignore errors raised from descriptors when collecting fixtures
Descriptors (e.g. properties) such as in the added test case are
triggered during collection, executing arbitrary code which can raise.
Previously, such exceptions were propagated and failed the collection.
Now these exceptions are caught and the corresponding attributes are
silently ignored.

A better solution would be to completely skip access to all custom
descriptors, such that the offending code doesn't even trigger. However
I think this requires manually going through the instance and all of its
MRO for each and every attribute checking if it might be a proper
fixture before accessing it. So I took the easy route here.

In other words, putting something like this in your test class is still
a bad idea...:

    @property
    def innocent(self):
        os.system('rm -rf /')

Fixes #2234.
2017-02-07 14:27:34 +02:00
Ran Benita
87fb689ab1 Remove an unneeded except KeyboardInterrupt
KeyboardInterrupt is a subclass of BaseException, but not of Exception.
Hence if we remove this except, KeyboardInterrupts will still be raised
so the behavior stays the same.
2017-02-07 14:12:09 +02:00
Bruno Oliveira
ccf9877447 Merge pull request #2232 from vidartf/patch-1
Do not asssume `Item.obj` in 'skipping' plugin
2017-02-03 21:39:42 -02:00
Bruno Oliveira
a4d2a5785b Merge pull request #2142 from barneygale/xfail_without_condition_getglobals
'xfail' markers without a condition no longer rely on the underlying `Item` objects deriving from `PyobjMixin`
2017-02-03 16:09:47 -02:00
Vidar Tonaas Fauske
832c89dd5f Test for pytest.mark.xfail with non-Python Item 2017-02-03 17:13:05 +01:00
Vidar Tonaas Fauske
1a88a91c7a Update authors/history 2017-02-03 16:29:43 +01:00
Vidar Tonaas Fauske
bad261279c Do not asssume Item.obj in 'skipping' plugin
See #2231 for discussion.
2017-02-03 16:04:34 +01:00
mbyt
ad56cd8027 extract a _handle_skip method, secure PY2 branch 2017-02-02 05:01:51 +01:00
Bruno Oliveira
176c680e19 Merge branch 'master' into allow_skipping_unittests_with_pdb_active 2017-02-01 15:53:14 -02:00
Ronny Pfannschmidt
da5a3dba87 Merge pull request #2226 from nicoddemus/raise-stop-iteration
Replace 'raise StopIteration' usages in the code by 'return's in accordance to PEP-479
2017-02-01 14:50:54 +01:00
Bruno Oliveira
e1c5314d80 Replace 'raise StopIteration' usages in the code by 'return's in accordance to PEP-479
Fix #2160
2017-02-01 02:37:55 -02:00
mbyt
36b6f17727 fixing code-style, keep flake8 happy 2017-01-31 21:03:49 +01:00
mbyt
d1c725078a Allow to skip unittests if --pdb active
closes #2137
2017-01-31 04:47:31 +01:00
Bruno Oliveira
0931fe2c89 Merge pull request #2221 from pytest-dev/ionelmc-patch-1
Discourage users from using unittest support somewhat
2017-01-25 21:38:44 -02:00
Ionel Cristian Mărieș
c8032a9bbb Fix reference. 2017-01-25 14:44:07 +02:00
Ionel Cristian Mărieș
d98d122e81 Discourage users from using this all the time. 2017-01-25 14:20:38 +02:00
Bruno Oliveira
beb77c1a38 Fix release date for 3.0.6 2017-01-23 13:51:12 -02:00
Ronny Pfannschmidt
d076e4158f Merge pull request #2216 from vmuriart/patch-1
Add py36 classifier & Add py37 to travis
2017-01-23 10:19:13 +01:00
Victor Uriarte
902fd2ff6a Add py37-nightly to travis 2017-01-22 17:20:15 -07:00
Victor Uriarte
839aa963a1 Add py36 identifier
and order AUTHORS
2017-01-22 17:13:17 -07:00
Ronny Pfannschmidt
400b0779f9 Merge pull request #2213 from RonnyPfannschmidt/release-3.0.6
Release 3.0.6
2017-01-22 22:21:53 +01:00
Ronny Pfannschmidt
c9f327dc87 bump version to next dev 2017-01-22 22:21:08 +01:00
Ronny Pfannschmidt
0e64cd045c take off author_email after pypi rejects 2017-01-22 22:14:54 +01:00
Ronny Pfannschmidt
22da561ae5 fix copy+paste error, its supposed to be 3.0.6 2017-01-22 18:44:30 +01:00
Ronny Pfannschmidt
449b88c640 rerun regendoc with correct install 2017-01-22 18:44:30 +01:00
Ronny Pfannschmidt
34b898b47e generate the release announcement 2017-01-22 18:44:30 +01:00
Ronny Pfannschmidt
01eaf9db51 fix the xfail docstring typo at the actual docstring + regendoc 2017-01-22 18:44:30 +01:00
Ronny Pfannschmidt
4d0c635252 regendoc 2017-01-22 18:44:30 +01:00
Ronny Pfannschmidt
55f21bd2b9 bump version 2017-01-22 18:44:30 +01:00
Bruno Oliveira
c39d846c1b Merge pull request #2215 from RonnyPfannschmidt/fix-doctesting/devpi-bug
fix devpi test for doctesting env
2017-01-22 13:02:03 -02:00
Ronny Pfannschmidt
403122281a fix devpi test for doctesting env
due to a devpi bug, we always get a sdist install which in turn triggers
the pytest issue #2042 / #726

going for pyargs and a changed folder, it should no longer happen
(and will be tested firther after rebasing the release branch)
2017-01-22 11:48:05 +01:00
Bruno Oliveira
15a3b57ec7 Merge pull request #2120 from RonnyPfannschmidt/fix-2118
fix #2118 - rework Node._getcustomclass and Node compat properties
2017-01-20 14:38:55 -02:00
Ronny Pfannschmidt
6a96b464ab update changelog as suggested 2017-01-20 15:26:59 +01:00
Ronny Pfannschmidt
7b4afd8946 remove unused import 2017-01-20 12:09:49 +01:00
Ronny Pfannschmidt
1a2d6388ac Merge pull request #2211 from nicoddemus/trial-envs
Fix pytester internal plugin to work correctly with latest versions of zope.interface
2017-01-20 12:08:12 +01:00
Bruno Oliveira
3766060893 Merge branch 'master' into trial-envs 2017-01-20 08:37:34 -02:00
Ronny Pfannschmidt
4082f4024a comment out compatproperty deprecations
todo: reenable in the features branch
2017-01-20 11:25:48 +01:00
Ronny Pfannschmidt
e0c48b4fe7 Merge pull request #2212 from nicoddemus/pytester-rewrite
Assert statements of the pytester plugin again benefit from assertion rewriting

fixes #1920
2017-01-20 10:04:12 +01:00
Bruno Oliveira
7b4368f3f4 Merge pull request #2184 from eli-b/parseoutcomes-explicit-failure
Fail assert_outcomes() on missing terminal report
2017-01-19 21:38:54 -02:00
Bruno Oliveira
c477f09177 Assert statements of the pytester plugin again benefit from assertion rewriting
Fix #1920
2017-01-19 21:33:51 -02:00
Bruno Oliveira
2574da8d32 Fix pytester internal plugin to work correctly with latest versions of zope.interface
Fix #1989
2017-01-19 20:53:35 -02:00
Ronny Pfannschmidt
d15724f74f Merge pull request #2204 from nicoddemus/linux-marker-doc
Fix marker example on "linux" platform
2017-01-18 09:34:34 +01:00
Bruno Oliveira
61fa91f3d0 Fix marker example on "linux" platform
I cheated a little and updated the example output by hand. 😁

Fix #2200
2017-01-17 21:09:04 -02:00
Ronny Pfannschmidt
125e89b7f8 Merge pull request #2194 from rjprins/remove-reinterp-from-docs
Remove mention of --assert=reinterp in documentation
2017-01-14 14:58:50 +01:00
Rutger Prins
46a9861d29 Remove mention of --assert=reinterp in documentation
Related to #1940
2017-01-13 22:35:37 +01:00
Bruno Oliveira
3dfdbaf490 Merge pull request #2186 from nicoddemus/pytest-plugins-env-rewrite
Consider plugins loaded by PYTEST_PLUGINS for assertion rewrite
2017-01-12 23:29:58 -02:00
Bruno Oliveira
7cd7c283dd Refactor plugin specs handling into an isolated function 2017-01-12 14:31:35 -02:00
Bruno Oliveira
043aadeaf2 Consider plugins loaded by PYTEST_PLUGINS for assertion rewrite
Fix #2185
2017-01-11 17:15:16 -02:00
Eli Boyarski
e18b2a427a Fail assert_outcomes() on missing terminal report
Currently if the terminal report of testdir.runpytest() is missing,
assert_outcomes() on its output fails because parseoutcomes()
returns an unexpected value (None).
It's better to fail parseoutcomes() directly.
2017-01-11 17:09:37 +02:00
Ronny Pfannschmidt
ff309b3584 Merge pull request #2182 from pombredanne/patch-1
Ensure the LICENSE is included in built wheels
2017-01-10 21:44:43 +01:00
Philippe Ombredanne
aa82db9fe2 Ensure the LICENSE is included in built wheels
Otherwise it is not included by default as wheels do not honor the MANIFEST.in

Signed-off-by: Philippe Ombredanne <pombredanne@nexb.com>
2017-01-10 19:25:57 +01:00
Bruno Oliveira
64cb67b703 Merge pull request #2174 from nicoddemus/appveyor-py36
Test py36 on AppVeyor
2017-01-05 22:35:20 -02:00
Bruno Oliveira
7559400183 Add py36 to test on AppVeyor
Fix #2134
2017-01-05 19:18:03 -02:00
Bruno Oliveira
9477f598d8 Merge pull request #2173 from jeffwidman/patch-1
Switch monkeypatch fixture to yield syntax
2017-01-04 23:17:30 -02:00
Jeff Widman
6d81c684cc Switch monkeypatch fixture to yield syntax 2017-01-04 15:06:52 -08:00
Bruno Oliveira
b769e41d8f Merge pull request #2170 from gogoengie/broken-links
Fix broken links
2017-01-02 21:57:17 -02:00
Peter Heatwole
ef903460b1 Fix broken links 2017-01-02 14:19:49 -08:00
Barney Gale
df409a0c0e Fix CHANGELOG.rst 2017-01-02 22:01:40 +00:00
Barney Gale
8db9915374 Update AUTHORS, CHANGELOG 2017-01-02 22:01:04 +00:00
Barney Gale
3d18c9c1c6 'xfail' markers without a condition no longer rely on the underlying Item
deriving from `PyobjMixin`
2017-01-02 22:01:04 +00:00
Bruno Oliveira
78f03888f4 Merge pull request #2168 from jwilk/spelling
Fix typos
2017-01-01 20:08:08 -02:00
Jakub Wilk
03a7a2cd3e Fix typos 2016-12-31 19:01:15 +01:00
Bruno Oliveira
7592c5b491 Sort issues and user references in CHANGELOG 2016-12-27 23:20:34 -02:00
Bruno Oliveira
091148f843 Merge pull request #2136 from hroncok/i2132
Tests: Check for ModuleNotFoundError on Python 3.6+
2016-12-27 23:10:58 -02:00
Bruno Oliveira
718f0b0255 Merge pull request #2130 from malinoff/fix-2129
Use inspect to properly detect generators. Fixes #2129
2016-12-27 22:11:46 -02:00
Bruno Oliveira
b4295aa19e Merge pull request #2144 from sscherfke/patch-1
Explicitly add setuptools to install_requires
2016-12-27 22:08:39 -02:00
Bruno Oliveira
7d259401cd Merge pull request #2161 from nicoddemus/silence-trial-on-ci
Allow trial environments to fail on CI for now
2016-12-27 22:04:50 -02:00
Bruno Oliveira
515fb09995 Move module error compatibility code to _pytest.compat 2016-12-27 22:01:22 -02:00
Bruno Oliveira
088b742d40 Merge pull request #2149 from pelme/issue2148
Fix handling of ini configuration in subdirs when specifying ::
2016-12-27 21:54:14 -02:00
Miro Hrončok
6b24ce2a9d Test Python 3.6 on Travis CI
Partial fix for https://github.com/pytest-dev/pytest/issues/2134
2016-12-27 23:16:25 +01:00
Miro Hrončok
1680eeb3a3 Tests: Check for ModuleNotFoundError on Python 3.6+
Those tests originally checked for ImportError. Since Python 3.6
ModuleNotFoundError is raised in this context instead, the tests didn't work
as they are text based (so exception inheritance does not save the day).

Fixes https://github.com/pytest-dev/pytest/issues/2132
2016-12-27 23:15:12 +01:00
Andreas Pelme
0bb8a4a36d Fixed #2148 - parse directory names properly when args contains ::.
This commit also improves readbility in get_dirs_from_args by using self
documenting local functions.

get_dirs_from_args also now only returns directories that actually exists,
and not files to avoid confusion.

This commit also removes redundant checks in get_common_ancestor that
was already performed in get_dirs_from_args..
2016-12-27 15:28:56 +01:00
Bruno Oliveira
f7a1d369c3 Allow trial environments to fail on CI for now
While I agree this is *far* from ideal, IMHO It is better to ignore them for now otherwise we hamper contributors with unrelated errors.

We should fix this before the next release.

#1989
2016-12-26 21:47:50 -02:00
Bruno Oliveira
316406291d Merge pull request #2150 from lesteve/add-caught-warnings-info-when-warns-fail
Improve error message when pytest.warns fail
2016-12-26 21:42:15 -02:00
Bruno Oliveira
a27c824fd0 Merge pull request #2146 from lwm/minor-docs-fixup
Fix fixture/parametrize override example.
2016-12-26 20:13:00 -02:00
Bruno Oliveira
fc74eb332b Merge pull request #2128 from nicoddemus/pytest-m
Mention that Python also adds CWD to sys.path using python -m
2016-12-26 20:11:59 -02:00
Loïc Estève
bfada968d3 Update AUTHORS and CHANGELOG.rst
following contribution guidelines
2016-12-20 14:36:10 +01:00
Loïc Estève
c5f0b751f4 Improve error message when pytest.warns fail
The error message contains the expected type of warnings and the
warnings that were captured. Add tests.
2016-12-20 13:45:39 +01:00
Luke Murphy
f94189b48b Fix wrong fixture name. Closes #2143. 2016-12-20 01:48:32 +01:00
Stefan Scherfke
3f5edc705a Explicitly add setuptools to install_requires
Setuptools is used in `_pytest/config.py` but was not explicitly listed as requirement. This led to an error when creating a Conda package for pytest since setuptools is not necessarily installed by default in Conda envs.
2016-12-19 13:22:25 +01:00
Bruno Oliveira
caee5ce489 Avoid importing asyncio directly because that in turn initializes logging (#8) 2016-12-13 21:54:20 -02:00
Bruno Oliveira
1312b83866 Add CHANGELOG entry for #2129 2016-12-13 21:33:01 -02:00
Bruno Oliveira
45eb9b566c Move compat tests to a single file using testdir
This avoids having to resort to skipping modules in conftest.py file and avoids flake8 errors
2016-12-13 21:28:07 -02:00
Dmitry Malinovsky
3a59acf69f Use inspect to properly detect generators. Fixes #2129 2016-12-11 21:59:11 +06:00
Bruno Oliveira
81c9bdcd0b Mention that Python also adds CWD to sys.path using python -m 2016-12-10 16:55:04 -02:00
Bruno Oliveira
da40bcf97f Merge pull request #2119 from nicoddemus/changelog-dates
Add release dates to CHANGELOG entries
2016-12-08 19:49:22 -02:00
Bruno Oliveira
a4a30ae4a2 Merge pull request #2123 from oscarh/documentation-issue-687
Also update yield teardown for Issue #687
2016-12-07 12:46:43 -02:00
Oscar Hellström
f42a954cb3 Also update yield teardown for Issue #687 2016-12-07 15:08:38 +01:00
Ronny Pfannschmidt
9c285dfc1d fix #2118 - rework Node._getcustomclass and Node compat properties 2016-12-06 09:13:25 +01:00
Bruno Oliveira
8afca5d0fa Add release dates to CHANGELOG entry
Fix #721
2016-12-05 17:21:01 -02:00
Bruno Oliveira
3a0a1d2de3 Bump version to 3.0.6.dev0 2016-12-05 12:51:00 -02:00
Bruno Oliveira
6a52afc8c9 Merge pull request #2116 from nicoddemus/release-3.0.5
Release 3.0.5
2016-12-05 12:42:32 -02:00
Bruno Oliveira
f592c7746a Regendocs for 3.0.5 2016-12-05 07:22:06 -05:00
Bruno Oliveira
31f114e51f Add release announcement for 3.0.5 2016-12-05 10:19:27 -02:00
Bruno Oliveira
833acb9d3c Finalize CHANGELOG for 3.0.5 2016-12-05 10:07:37 -02:00
Bruno Oliveira
0febd855e1 Bump version to 3.0.5 2016-12-05 10:06:58 -02:00
Ronny Pfannschmidt
3c81f83602 Merge pull request #2113 from nicoddemus/approx-repr-unicode
Use a simple ``+-`` ASCII string in the string representation of pytest.approx In Python 2
2016-12-05 13:02:07 +01:00
Bruno Oliveira
57c4489916 Use a simple `+-` ASCII string in the string representation of pytest.approx In Python 2
Fix #2111
2016-12-02 20:01:53 -02:00
Bruno Oliveira
5365f7c9ca Merge pull request #2112 from ismail-s/patch-1
Fix minor typo
2016-12-02 14:12:06 -02:00
Ismail
1f0401ab62 Fix minor typo 2016-12-02 15:09:38 +00:00
Bruno Oliveira
7480342710 Fix typo in docstring of register_assert_rewrite 2016-12-02 09:22:47 -02:00
Bruno Oliveira
db62f160e1 Merge pull request #2073 from nicoddemus/fix-hookproxy-cache
Remove hook proxy cache
2016-12-02 09:07:20 -02:00
Bruno Oliveira
81528ea81f Remove hook proxy cache
Fix #2016
2016-12-02 07:32:11 -02:00
Ronny Pfannschmidt
64193add91 Merge pull request #2110 from nicoddemus/rewrite-warning-pytest-plugins
Fix false-positive assert rewrite warnings when using 'pytest_plugins'
2016-12-01 20:33:38 +01:00
Bruno Oliveira
bc0f7e6243 Fix false-positive assert rewrite warnings when using 'pytest_plugins'
pytest would emit false positive warnings about assertion-rewrite when a
module appears multiple times in plugins which depend
on other plugins using the 'pytest_plugins' mechanism
2016-12-01 15:50:08 -02:00
Ronny Pfannschmidt
9ed3d76b51 Merge pull request #2108 from lwm/exp-2105
Add warning for incorrect passing args to `-o`.
2016-12-01 13:49:24 +01:00
Luke Murphy
c856537e71 Add warning for incorrect passing args to -o. 2016-12-01 13:20:42 +01:00
Ronny Pfannschmidt
e612619aea Merge pull request #2106 from nicoddemus/sys-modules-none
Remove support code for earlier Python 3 version in Source.compile
2016-12-01 10:22:32 +01:00
Bruno Oliveira
30f0152ae6 Remove unused import 2016-11-30 22:34:02 -02:00
Bruno Oliveira
f8d195253e Remove support code for earlier Python 3 version in Source.compile
This code leaves None in sys.modules as a side effect but is no longer needed in the Python 3 versions we support.

Fix #2103
2016-11-30 22:23:02 -02:00
Bruno Oliveira
8208a77a3e Merge pull request #2098 from DuncanBetts/master
Improved description of functionality for Issue #687
2016-11-28 23:05:27 -02:00
Bruno Oliveira
8b4da9d955 Merge pull request #2100 from blueyed/fix-help-grammar
minor: fix grammar with help for --setup-{only,show}
2016-11-28 20:11:56 -02:00
Bruno Oliveira
454d288138 Merge pull request #2097 from lwm/junitxml-warn
Add `type` validation.
2016-11-28 20:10:51 -02:00
Daniel Hahler
40cffacadc minor: fix grammar with help for --setup-{only,show} 2016-11-28 21:33:15 +01:00
Duncan Betts
6473c3d87e Improved description of functionality for Issue #687 2016-11-28 14:30:25 +00:00
Luke Murphy
4e1609b12e Add type validation.
Argparse driven argument type validation is added for the
`--junit-xml` and `--confcutdir` arguments.

The commit partially reverts #2080. Closes #2089.
2016-11-28 02:16:01 +01:00
Bruno Oliveira
0735d4549d Merge pull request #2088 from nmundar/issue-2034
Issue 2034
2016-11-27 16:12:31 -02:00
Ronny Pfannschmidt
f25ba4dd0b Merge pull request #2095 from nicoddemus/readme-example
Use "inc" instead of "func" in the snipped on README
2016-11-27 19:11:35 +01:00
Bruno Oliveira
788e394c93 Use "inc" instead of "func" in the snipped on README and doc index
"inc" reads better, also fixed the line separators so
they have the same size
2016-11-27 15:49:39 -02:00
Bruno Oliveira
2d7197926a Improve CHANGELOG entry for #2034 2016-11-27 14:26:30 -02:00
nmundar
0a30f072e6 Show name argment in compatproperty deprecation message 2016-11-27 14:24:55 -02:00
nmundar
0e6ad8e59f update CHANGELOG and AUTHORS 2016-11-27 14:24:55 -02:00
nmundar
b38fad4b82 Add compatproperty deprecation warning. 2016-11-27 14:24:55 -02:00
Bruno Oliveira
483754216f Merge pull request #2094 from nicoddemus/remove-setuptools-pin
Remove setuptools pin now that upstream has been fixed
2016-11-27 14:15:47 -02:00
Bruno Oliveira
1e97ea60f7 Merge pull request #2091 from lwm/move-595-along
Add test case for #595.
2016-11-27 14:13:15 -02:00
Ronny Pfannschmidt
58f28bf049 Merge pull request #2093 from lwm/add-docs-notes
Add documentation building note.
2016-11-27 10:13:28 +01:00
Bruno Oliveira
5566b3ccb6 Remove setuptools pin now that upstream has been fixed
Related to pypa/setuptools#861
2016-11-27 03:30:23 -02:00
Bruno Oliveira
8138d88da2 Merge pull request #2087 from lwm/ref-recwarns
Add `:ref:` targets to `recwarn.rst`.
2016-11-26 18:06:17 -02:00
Luke Murphy
0aa891543d Add documentation building note. 2016-11-26 18:57:51 +01:00
Luke Murphy
6c5475660a Add test case for #595.
This new test proves that reports do not capture stdout
by default when skipped.
2016-11-26 18:49:24 +01:00
Luke Murphy
1aa5bfea11 Add :ref: targets to recwarn.rst. 2016-11-26 18:41:38 +01:00
Bruno Oliveira
a6084ed797 Merge pull request #2090 from avojnovicDk/issue-1808
Clarify test discovery docs.
2016-11-26 15:28:06 -02:00
Bruno Oliveira
d05d19da78 Merge pull request #2085 from DuncanBetts/master
Add hint of Issue #478 to error text
2016-11-26 15:25:54 -02:00
Bruno Oliveira
fa4d5da4ca Merge pull request #2092 from nicoddemus/pin-setuptools
Pin setuptools to < 29 because of AppVeyor failures
2016-11-26 15:25:43 -02:00
Bruno Oliveira
6120570198 Pin setuptools to < 29 because of AppVeyor failures
Related to pypa/setuptools#861

Remove the pin when we have a new setuptools release
2016-11-26 14:49:31 -02:00
Ana Vojnovic
2e6a58ab69 Clarify test discovery docs. 2016-11-26 15:21:39 +01:00
Duncan Betts
c1b83cdeea Add hint of Issue #478 to error text 2016-11-26 10:47:15 +00:00
Bruno Oliveira
33796c8a13 Merge pull request #2084 from nicoddemus/fix-coveralls-appveyor
Only execute "coveralls" toxenv once on AppVeyor
2016-11-24 19:43:52 -02:00
Bruno Oliveira
8763590eef Only execute "coveralls" toxenv on master once
Just noticed that the "coveralls" env was being execute after each env.

This was introduced by mistake in #2056
2016-11-24 19:27:27 -02:00
Ronny Pfannschmidt
b3efd9aa59 Merge pull request #2083 from nicoddemus/approx-check-float
Fix error in approx's repr with complex numbers
2016-11-24 19:40:29 +01:00
Bruno Oliveira
33c0b06fdf Fix error in approx's repr with complex numbers
Fix #2082
2016-11-24 15:33:12 -02:00
Bruno Oliveira
38f7562c7c Merge pull request #2080 from nicoddemus/confcutdir-check
Show an error if --confcutdir is not a valid directory
2016-11-23 10:23:01 -02:00
Bruno Oliveira
629d8e9fd6 Show an error if --confcutdir is not a valid directory
Fixes #2078
2016-11-23 09:49:11 -02:00
Ronny Pfannschmidt
a5b5090c72 Merge pull request #2070 from nedbat/bug2038
Don't fail if imp can't find the source for a .pyc file. #2038
2016-11-22 17:45:29 +01:00
Ronny Pfannschmidt
a3319ffe80 Merge pull request #2071 from nicoddemus/fix-flake8
Fix flake8 E305 and E306 errors
2016-11-22 13:22:11 +01:00
Bruno Oliveira
1e2b2af296 Merge pull request #2074 from nedbat/fix-double-spaces
Remove an accidental double space
2016-11-21 14:19:56 -02:00
Ned Batchelder
632c4d5daf Remove an accidental double space 2016-11-21 10:17:23 -05:00
Bruno Oliveira
984d4ce5ec Fix test_excinfo_getstatement that broke because of whitespace changes 2016-11-20 19:12:42 -02:00
Bruno Oliveira
1eb5a690d4 Fix flake8 E305 and E306 errors
These errors started to appear with flake8-3.1.1, while they don't appear with
version 3.1.0 (weird).
2016-11-20 18:59:15 -02:00
Ned Batchelder
06bb61bbe3 Don't fail if imp can't find the source for a .pyc file. #2038 2016-11-20 13:09:32 -05:00
Bruno Oliveira
cbf261c74e Merge pull request #2065 from sebastinas/spelling2
Fix spelling mistakes
2016-11-15 22:51:49 -02:00
Sebastian Ramacher
0ba930a11d Fix spelling mistakes
Signed-off-by: Sebastian Ramacher <sramacher@debian.org>
2016-11-15 23:05:58 +01:00
Bruno Oliveira
73d481552d Merge pull request #2058 from idlesign/patch-1
Docs: Added pytest promotional talk in Russian
2016-11-13 11:06:35 -02:00
Igor Starikov
50328f47db Docs: Added pytest promotional talk in Russian 2016-11-13 18:04:39 +07:00
Bruno Oliveira
f0e0250cd5 Merge pull request #2056 from nicoddemus/appveyor-list
Use one job for each tox env on AppVeyor
2016-11-12 22:15:41 -02:00
Bruno Oliveira
ec69514eb2 Only install pypy on AppVeyor for "pypy" tox-env 2016-11-12 20:20:59 -02:00
Bruno Oliveira
c169c883d3 Use one job for each tox env on AppVeyor
Some time ago when we first added support for testing pytest on AppVeyor,
jobs in a build would not start immediately one after the other, as if AppVeyor
would schedule jobs from other builds (projects) in its VMs. So it made sense
at the time to reduce the number of jobs.

I have noticed in other projects that this behavior has changed, and jobs
in a build now start one after the other. Having a separate list then improves
visibility when the build fails, because we can see at a glance the failing(s)
tox environment(s).
2016-11-12 12:49:12 -02:00
Bruno Oliveira
5185f2a6ae Merge pull request #2053 from nicoddemus/check-manifest-script
Use a wrapper script to bypass check-manifest if not under git
2016-11-12 12:12:54 -02:00
Bruno Oliveira
351395b7ea Use a wrapper script to bypass check-manifest if not under git
Related to comment in #2051
2016-11-12 11:39:41 -02:00
Ronny Pfannschmidt
71b68334e2 Merge pull request #2055 from nicoddemus/error-matrix-for-failing-jobs
Allow problematic jobs to fail instead of commenting them out
2016-11-11 22:38:33 +01:00
Bruno Oliveira
98caeedd9e Allow failure of pypy on AppVeyor
Related to #1963
2016-11-11 19:26:58 -02:00
Bruno Oliveira
1519b38af0 Allow failure of py35-trial on Travis
Related to #1989
2016-11-11 19:26:54 -02:00
Bruno Oliveira
3e01e83390 Bump version to 3.0.5.dev 2016-11-11 18:20:34 -02:00
Bruno Oliveira
ad4ef4f583 Merge pull request #2050 from nicoddemus/release-3.0.4
Release 3.0.4
2016-11-11 18:11:49 -02:00
Ronny Pfannschmidt
5717c71179 Merge pull request #2052 from nicoddemus/lint-readme
Check README.rst with rst-lint
2016-11-11 18:04:50 +01:00
Ronny Pfannschmidt
6c8c1da428 add pygments dependency because of rst-lint 2016-11-11 14:25:53 -02:00
Bruno Oliveira
b8c6f13b37 Check README.rst with rst-lint 2016-11-11 12:56:07 -02:00
Bruno Oliveira
8e0f7d3793 Merge pull request #2051 from nicoddemus/check-manifest
Check manifest
2016-11-10 22:58:48 -02:00
Bruno Oliveira
aaa547e763 Add some recursive-exclude related to hypothesis and freeze 2016-11-10 08:48:56 -02:00
Bruno Oliveira
26b1519534 Add keywords to setup.py as suggested by pyroma
Related to #1
2016-11-09 20:47:14 -02:00
Bruno Oliveira
84d7068723 Add "check-manifest" to linting and remove unused scripts from root
Fix #1
2016-11-09 20:42:28 -02:00
Bruno Oliveira
ab274299fe Regen doc for 3.0.4 2016-11-09 16:44:58 -05:00
Bruno Oliveira
ff72db2f1a Version bump to 3.0.4, CHANGELOG, announcement 2016-11-09 19:38:11 -02:00
Bruno Oliveira
fc304b8b44 Merge pull request #2006 from MSeifert04/fix-1965
Fix memory leak with pytest.raises by using weakref
2016-11-09 19:19:40 -02:00
Bruno Oliveira
1130b9f742 Fix the stubborn test about cyclic references left by pytest.raises
In Python 2, a context manager's __exit__() leaves sys.exc_info with the exception values even when it was supposed
to suppress the exception, so we explicitly call sys.exc_clear() which removes the traceback and allow the object
to be released.

Also updated the test to not depend on the immediate destruction of the object but instead to ensure it is not being
tracked as a cyclic reference.

Fix #1965
2016-11-08 22:20:27 -02:00
Michael Seifert
552c7d4286 added test (thanks @nicoddemus) and added links in Changelog 2016-11-08 22:13:02 -02:00
Michael Seifert
1e5b21cd61 Fix memory leak with pytest.raises by using weakref 2016-11-08 22:12:23 -02:00
Bruno Oliveira
0b94c43bac Merge pull request #2046 from d-b-w/clean-up-unittest-issue1649
Clean up unittest TestCase objects after tests are complete (#1649).
2016-11-08 15:23:46 -02:00
Dan Wandschneider
e46e653794 Clean up unittest TestCase objects after tests are complete (#1649).
Fix #1649

Users of unittest style TestCases will create expensive objects
in setUp. We should clean up TestCase instances that are lying
around so that they don't fill up memory.
2016-11-07 18:32:56 -08:00
Ronny Pfannschmidt
07af307e4a Merge pull request #2045 from manueljacob/normalized-version
Change version to be in normal form according to PEP 440.
2016-11-06 12:30:22 +01:00
Manuel Jacob
a190ad27f2 Change version to be in normal form according to PEP 440.
The version is changed from 3.0.4.dev to 3.0.4.dev0.  Note that
according to PEP 440 these are considered equivalent, but 3.0.4.dev0 is
the normal form.

This standard was followed when the version was set to 3.0.3.dev0 in
commit ee284ec5, but in commit a87b1c79 the version was set to
3.0.4.dev, leaving the development number implicit again.
2016-11-06 09:00:04 +01:00
Bruno Oliveira
f331e8f576 Merge pull request #2028 from nicoddemus/empty-tracebacks
Properly handle exceptions in multiprocessing tasks
2016-11-03 12:18:38 -02:00
Bruno Oliveira
006a901b86 Properly handle exceptions in multiprocessing tasks
Fix #1984
2016-11-03 10:48:43 -02:00
Ronny Pfannschmidt
45b21fa9b0 Merge pull request #2041 from gdyuldin/fix_xuint_teardown
Fix teardown error message in generated xUnit XML
2016-11-02 15:24:53 +01:00
Georgy Dyuldin
e2bb4f893b Fix teardown error message in generated xUnit XML
It was "test setup failure" even error happens on test teardown.
2016-11-02 15:50:32 +03:00
Bruno Oliveira
e3544553b7 Merge pull request #2030 from matclab/fix/442
Report teardown output on test failure
2016-10-31 13:50:50 -02:00
Ronny Pfannschmidt
1e6ed2a25a Merge pull request #2033 from The-Compiler/workshop
Update "Next Open Trainings"
2016-10-31 07:52:42 +01:00
Florian Bruhin
382fa231a1 Update "Next Open Trainings" 2016-10-31 06:49:06 +01:00
Mathieu Clabaut
6f93ffb5d4 Report teardown output on test failure
Until now, teardown stdout/stderr output was not reported upon test failure.
However such output is sometime necessary to understand the failure.

fix #442
2016-10-30 09:52:46 +01:00
Ronny Pfannschmidt
35d154f580 Merge pull request #2011 from nicoddemus/false-rewrite-warnings
Fix false-positive warnings from assertion rewrite hook
2016-10-24 12:19:23 +02:00
Ronny Pfannschmidt
4e9c633185 Merge pull request #2021 from nicoddemus/doctest-modules-ci
Re-enable docstring testing of _pytest modules on CI
2016-10-24 12:19:05 +02:00
Bruno Oliveira
7f95ea31d5 Merge pull request #2024 from jaraco/issue-2022
Restore pexpect tests on macOS. Fixes #2022.
2016-10-21 17:17:14 -02:00
Jason R. Coombs
f2c01c5407 Restore pexpect tests and bypass isalive/wait on macOS. Ref #2022. 2016-10-21 12:36:42 -04:00
Jason R. Coombs
60a347aeb5 Also use flush where wait was called unconditionally 2016-10-21 12:11:35 -04:00
Jason R. Coombs
11ec96a927 Extract child flush as a staticmethod 2016-10-21 12:10:35 -04:00
Bruno Oliveira
37dcdfbc58 Re-enable docstring testing of _pytest modules on CI
* Fix doctests
* List one env per line in tox.ini
* "doctesting" tox env now also tests docstrings using doctest
2016-10-21 08:55:53 -02:00
Bruno Oliveira
2a2b8cee09 Fix false-positive warnings from assertion rewrite hook
Fix #2005
2016-10-20 21:40:57 -02:00
Ronny Pfannschmidt
82fb63ca2d Merge pull request #2019 from nicoddemus/fix-metavar-pair-help
Fix cmdline help message for custom options with two or more metavars
2016-10-21 01:36:24 +02:00
Bruno Oliveira
620b384b69 Fix cmdline help message for custom options with two or more metavars
Fix #2004
2016-10-20 20:34:39 -02:00
Ronny Pfannschmidt
5cbfefbba0 Merge pull request #2018 from nicoddemus/disable-py35-trial
Disable py35-trial while #1989 is not fixed
2016-10-20 23:18:48 +02:00
Bruno Oliveira
95007ddeca Disable py35-trial while #1989 is not fixed 2016-10-20 18:56:54 -02:00
Ronny Pfannschmidt
995e60efbf Merge pull request #2017 from nicoddemus/pytest-main-args-docs
Remove example of obsolete pytest.main usage with string
2016-10-20 18:29:54 +02:00
Bruno Oliveira
918af99a2a Remove example of obsolete pytest.main usage with string 2016-10-20 12:30:58 -02:00
Ronny Pfannschmidt
c0719a5b4c Merge pull request #2009 from pytest-dev/RonnyPfannschmidt-patch-docs-remove-main-string
docs: remove mention of string args to main

closes #2008
2016-10-18 17:52:15 +02:00
Ronny Pfannschmidt
afc1e2b0e1 docs: remove mention of string args to main
fixes #2008

string args got deprecated due to the insane amount of edge-cases wrt splitting on windows vs posix
2016-10-18 17:21:40 +02:00
Ronny Pfannschmidt
de1614923f Merge pull request #2000 from nicoddemus/issue-1998
Handle import errors with non-ascii messages when importing plugins
2016-10-17 21:13:56 +02:00
Bruno Oliveira
bc1f8666aa Fix link in CHANGELOG for #1853 2016-10-12 18:19:34 -03:00
Bruno Oliveira
78eec0d7f8 Handle import errors with non-ascii messages when importing plugins
Fix #1998
2016-10-12 18:19:32 -03:00
Bruno Oliveira
3301a1c173 Merge pull request #1987 from Budulianin/master
Update fixture.rst
2016-10-05 17:01:11 -03:00
Grigorii Eremeev
65ebc75ee8 Update fixture.rst
Removed redundant word
2016-10-05 22:26:13 +03:00
Bruno Oliveira
cf13355d3f Merge pull request #1979 from nicoddemus/show-traceback-during-collection
Show traceback during collection
2016-10-05 16:18:43 -03:00
Florian Bruhin
1289cbb9a5 Merge pull request #1988 from nicoddemus/pr-template-small-fixes
Mention small doc fixes don't need tests/changelog entries in PR template
2016-10-05 21:10:36 +02:00
Bruno Oliveira
10433db225 Mention small doc fixes don't need tests/changelog entries in PR template 2016-10-05 15:36:38 -03:00
Bruno Oliveira
50b960c1f0 Add note about not monkey-patching builtins (#1986)
* Add note about not monkey-patching builtins

Related to #1985

* Mention -s as well
2016-10-05 17:57:40 +02:00
Bruno Oliveira
d47ae799a7 Merge pull request #1983 from pytest-dev/fix-1981-improve-ini-options-help-text
Fix #1981, improve ini-options help text
2016-10-04 12:43:42 -03:00
Tom V
c93a9e3361 Fix #1981, improve ini-options help text 2016-10-04 14:41:09 +01:00
Bruno Oliveira
a1d446b8e8 Display traceback from Import errors using pytest's short representation
Also omit pytest's own modules and internal libraries (py and pluggy) in low verbosity

Fix #1976
2016-10-03 21:46:44 -03:00
Bruno Oliveira
7d66e4eae1 Display full traceback from Import errors when collecting test modules
Fix #1976
2016-10-03 20:47:44 -03:00
Bruno Oliveira
fc02003220 Merge pull request #1975 from nicoddemus/pytest-skip-message
Pytest skip message
2016-10-01 14:44:49 -03:00
Bruno Oliveira
336d7900c5 Fix test about pytest.skip message being used at global level
Fix #1959
2016-10-01 13:38:52 -03:00
Nikolaus Rath
57bb3c6922 Improve error message when using pytest.skip at module level
As discussed in issue #1959.
2016-10-01 13:38:52 -03:00
Bruno Oliveira
a87b1c79c1 post 3.0.3 release changes 2016-09-29 18:58:17 -03:00
Bruno Oliveira
30f3d95aeb Merge pull request #1973 from nicoddemus/release-3.0.3
Release 3.0.3
2016-09-29 18:54:50 -03:00
Bruno Oliveira
ba6ecc14c8 Include release-3.0.3 into the announce toctree 2016-09-28 17:16:57 -04:00
Bruno Oliveira
41d3b3f4f9 Regendoc for version 3.0.3 2016-09-28 16:36:15 -04:00
Bruno Oliveira
dda17994ec Prepare for 3.0.3 release 2016-09-28 16:33:38 -04:00
Bruno Oliveira
427cee109a Merge pull request #1964 from nicoddemus/pluggy-0.4.0
Vendor pluggy 0.4.0
2016-09-27 17:35:51 -03:00
Florian Bruhin
30d459e2e3 Merge pull request #1968 from nicoddemus/use-latest-hypothesis
Use hypothesis >= 3.5.2
2016-09-26 15:01:09 +02:00
Bruno Oliveira
f31447b82b Use hypothesis >= 3.5.2
Related to #1962
2016-09-26 09:08:30 -03:00
Florian Bruhin
b071fdc633 Merge pull request #1960 from nicoddemus/skip-module-level-doc
Add a note about pytest.skip not being allowed at module level
2016-09-26 08:37:14 +02:00
Bruno Oliveira
19766ef0bc Add a summary on how to skip all tests in a module in different situations 2016-09-25 23:36:25 -03:00
Bruno Oliveira
94155ee62a Add a note about pytest.skip not being allowed at module level 2016-09-25 23:36:25 -03:00
Bruno Oliveira
835328d862 Vendor pluggy 0.4.0
Fix #1637
2016-09-25 23:36:02 -03:00
Bruno Oliveira
8dc497b54b Merge pull request #1966 from nicoddemus/disable-pypy-windows
Disable pypy on AppVeyor until #1963 gets fixed
2016-09-25 23:34:59 -03:00
Bruno Oliveira
da201c7d29 Disable pypy on AppVeyor until #1963 gets fixed 2016-09-25 23:21:37 -03:00
Bruno Oliveira
01068e5571 Merge pull request #1962 from nicoddemus/fix-ci
Pin hypothesis to 3.5.0 because 3.5.1 breaks the test suite
2016-09-25 21:17:17 -03:00
Bruno Oliveira
73cab77249 Pin hypothesis to 3.5.0 because 3.5.1 breaks the test suite
Related to HypothesisWorks/hypothesis-python#368
2016-09-25 18:52:27 -03:00
Bruno Oliveira
09bcf7f170 Merge pull request #1958 from rowillia/master
Remove implementation of `__getslice__`
2016-09-24 08:39:58 -03:00
Roy Williams
f1c4cfea2c Remove implementation of __getslice__
`__getslice__` has been Deprecated since Python 2.0 and is removed in Python 3.  See
https://docs.python.org/2/reference/datamodel.html#object.__getslice__

Unfortunately, Python 2 will still dispatch to `__getslice__` over `__getitem__`, See
http://bugs.python.org/issue2041, which causes Warnings when running with `-3` in 2.7.
2016-09-23 09:52:30 -07:00
Bruno Oliveira
e5deb8a927 Merge pull request #1955 from rowillia/fix_python3_deprecation_warnings
Fix `DeprecationWarnings` found when running py.test in Python 2.7 with the -3 flag.
2016-09-22 17:37:52 -03:00
Roy Williams
24db3c123d Explicitly set to None to have consistent behavior in Python 2 and Python 3 2016-09-22 09:22:12 -07:00
Roy Williams
940ed7e943 Fix DeprecationWarnings found when running py.test in Python 2.7 with the -3 flag.
Running through some of my tests with the `-3` flag in python2.7 I encountered some errors within py.test itself.  This fixes those errors so we can use py.test in order to identify problems with Python 3.
2016-09-21 17:44:25 -07:00
Bruno Oliveira
f279bd2bd5 Merge pull request #1918 from tgoodlet/explain_bad_scope
Explain a bad scope value to the user
2016-09-21 18:58:03 -03:00
Tyler Goodlet
6db2f315fa Explain a bad scope value to the user 2016-09-21 16:40:58 -04:00
Florian Bruhin
7660a19d0a Merge pull request #1945 from axil/master
AttributeError chaining bug #1944 fix
2016-09-20 08:36:04 +02:00
Lev Maximov
8cba033bbb added a test 2016-09-20 02:47:59 +07:00
Lev Maximov
6b56c36ae7 added to changelog and authors 2016-09-20 02:47:59 +07:00
Lev Maximov
65be1231b1 AttributeError chaining bug #1944 fix 2016-09-20 02:20:13 +07:00
Floris Bruynooghe
8639bf7554 fixup! Merge pkg_resources workaround 2016-09-19 10:20:36 +01:00
Floris Bruynooghe
f484e7c9ca Merge pkg_resources workaround
Merge branch 'pkg_resources_bugfix' of github.com:raquel-ucl/pytest into pkg-resources

This is an odd case and doesn't really make sense, it is working around a bug
in maven/jython and the old version or weird packaging of setuptools they use.
But we used to do this in the past so might as well keep doing this.
2016-09-19 10:14:41 +01:00
Ronny Pfannschmidt
2bafa74765 Merge pull request #1942 from mbyt/better_doc_for_1890
better doc for #1890 based on #1932
2016-09-17 20:14:44 +02:00
mbyt
77d842ceb2 better doc for #1890 based on #1932 2016-09-17 19:58:27 +02:00
Bruno Oliveira
863b7d0c50 Merge pull request #1933 from pytest-dev/metafunc-members-docs
Remove duplicated for Metafunc members on docs
2016-09-15 12:43:54 -03:00
Ronny Pfannschmidt
40ec35767f Merge pull request #1935 from nicoddemus/assert-rewrite-dev-plugins
Fixed assertion rewriting for plugins in development mode
2016-09-15 08:45:23 +02:00
Bruno Oliveira
04cf5e1df4 Fixed assertion rewriting for plugins in development mode
Fix #1934
2016-09-14 21:59:33 -03:00
Bruno Oliveira
138e255631 Remove duplicated for Metafunc members on docs
Fix #1924
2016-09-14 17:11:58 -03:00
Bruno Oliveira
51378aba01 Merge pull request #1919 from The-Compiler/pdf
Fix link to PDF docs
2016-09-07 16:23:26 -03:00
Florian Bruhin
8e67dd13e7 Fix link to PDF docs
Fixes #1917
2016-09-06 21:17:54 +02:00
Bruno Oliveira
99efc281ee Merge pull request #1914 from RonnyPfannschmidt/docs-remove-getdoctarget
docs: remove the need for special scripts
2016-09-05 16:38:41 -03:00
Ronny Pfannschmidt
a2b8981b50 docs: remove unused helper script 2016-09-05 21:03:22 +02:00
Ronny Pfannschmidt
e21ae3991d docs: remove the need for special scripts
* import version from pytest since it is importable
* remove makefile bits from legacy hosting
* remove the script to determine the version for legacy hosting
2016-09-05 16:42:33 +02:00
Florian Bruhin
8a41b26f56 Merge pull request #1908 from nicoddemus/parametrize-unicode-id
The "ids" argument to "parametrize" again accepts unicode strings in Python 2
2016-09-05 15:09:12 +02:00
Ronny Pfannschmidt
b6f766ae87 Merge pull request #1912 from flub/reg-assert-rewrite-changelog
Mention register_assert_rewrite explicitly
2016-09-05 14:36:05 +02:00
Floris Bruynooghe
ceeb5149f3 Mention register_assert_rewrite explicitly
It helps mentioning this explicitly in the changelog.
Fixes #1871.
2016-09-05 13:09:36 +01:00
Florian Bruhin
b38cf77562 Merge pull request #1911 from irachex/patch-1
Fix keyword docs
2016-09-05 11:27:49 +02:00
Huayi Zhang
c60854474a Fix keyword docs 2016-09-05 16:48:04 +08:00
Ronny Pfannschmidt
c69fbd79a9 Merge pull request #1910 from nicoddemus/monkeypatch-members-docs
Fix reference docs for monkeypatch
2016-09-03 21:13:54 +02:00
Bruno Oliveira
183f3737d4 Fix reference docs for monkeypatch
Fix #1909
2016-09-03 15:47:54 -03:00
Bruno Oliveira
1e10de574d The "ids" argument to "parametrize" again accepts unicode strings in Python 2
Fixes #1905
2016-09-02 18:38:15 -03:00
Florian Bruhin
722f9eadcd Merge pull request #1906 from pytest-dev/adjustment-how-to-release
Send only minor/major release announces to TIP mailing list
2016-09-02 18:10:29 +02:00
Bruno Oliveira
7a4fe7582c Send only minor/major release announces to TIP mailing list
As discussed recently on the testing-in-python mailing list, people have asked 
to restrict the amount of announcements there only to major/minor 
pytest releases
2016-09-02 12:27:06 -03:00
Bruno Oliveira
96a1d2941b Merge pull request #1900 from nicoddemus/finalize-3.0.2-release
Finalize 3.0.2 release
2016-09-01 23:05:39 -03:00
Bruno Oliveira
ee284ec587 Set version to 3.0.3.dev0
Also, using "dev0" as development suffix otherwise distutils gives a warning during "setup.py develop":

UserWarning: Normalizing '3.0.3.dev' to '3.0.3.dev0'
  normalized_version,
2016-09-01 21:34:54 -03:00
Bruno Oliveira
927f411ee2 Fix release 3.0.2 release announcement list of authors 2016-09-01 21:28:30 -03:00
Bruno Oliveira
919f50a3bd Merge pull request #1896 from nicoddemus/release-3.0.2
Release 3.0.2
2016-09-01 21:19:50 -03:00
Bruno Oliveira
4e58c9a7d0 Fix use of deprecated getfuncargvalue method in the internal doctest plugin
Fix #1898
2016-09-01 07:19:11 -04:00
Bruno Oliveira
a9f3053f72 Fix version typo in announce for 3.0.2 2016-09-01 06:59:31 -04:00
Bruno Oliveira
d512e7f26b Run regendoc for 3.0.2 release 2016-08-31 20:32:05 -04:00
Bruno Oliveira
f985f47a02 Fix reportingdemo call to pytest 2016-08-31 20:30:06 -04:00
Bruno Oliveira
4c45b93007 Changes for 3.0.2 release 2016-08-31 20:28:38 -04:00
Bruno Oliveira
a094fb3aa6 Merge pull request #1890 from mbyt/disable_tearDown_and_cleanups_for_post_mortem_debugging
unittest runner: avoid tearDown and cleanup to ease post mortem debugging
2016-08-31 21:09:45 -03:00
mbyt
e43d1174f7 spelling 2016-08-31 22:46:40 +02:00
mbyt
696a9112be integrating review commets of @nicoddemus
plus small scale refactoring
2016-08-31 22:33:47 +02:00
mbyt
be08223d5a Merge branch 'master' into disable_tearDown_and_cleanups_for_post_mortem_debugging
Conflicts:
	CHANGELOG.rst
2016-08-31 20:35:31 +02:00
mbyt
10b3274924 adding corresponding test, authors and changelog 2016-08-31 20:22:54 +02:00
Florian Bruhin
67ba8aaaa2 Merge pull request #1891 from nicoddemus/find-spec-rewrite-hook
Fix issue pytest_plugins as string was marking wrong modules for rewrite
2016-08-31 05:23:33 +02:00
Bruno Oliveira
edf8283bd8 Add CHANGELOG entry for #1888 2016-08-30 23:13:27 -03:00
Bruno Oliveira
c8a366e551 Fix issue where pytest_plugins as string was marking wrong modules for rewrite
Fix #1888
2016-08-30 22:53:50 -03:00
mbyt
4eeb475138 avoid tearDown and cleanup for unittest debugging 2016-08-30 21:55:49 +02:00
Bruno Oliveira
82218e4ee1 Merge pull request #1887 from mbyt/pdbcls_example_with_tab_completion
pdbcls ipython example with tab completion
2016-08-29 17:11:51 -03:00
mbyt
8593bb12ee pdbcls ipython example with tab completion 2016-08-29 21:15:12 +02:00
Raphael Pierzina
e75078eae2 Merge pull request #1848 from pytest-dev/doc-warnings
docs warnings as errors and initial page similar to README
2016-08-26 23:02:28 +01:00
Bruno Oliveira
519f02b014 docs warnings as errors and initial page similar to README
* Changed "index" to be more similar to the README (#1708).
* Fixes numerous issues like missing documents, syntax errors, etc (#1829, #432).
* Mention all docs in "contents.rst" so it's easier for users to locate (#1112).
* Add doc generation and checking to Travis and AppVeyor, to avoid re-introducing errors.

Fixes #432, Fixes #1112, Fixes #1708, Fixes #1829
2016-08-26 17:47:18 -03:00
Florian Bruhin
cb7c472e34 Merge pull request #1876 from nicoddemus/remove-monkeypatch-invocation-example
Remove example of "monkeypatch" used in session scope
2016-08-26 06:15:07 +02:00
Bruno Oliveira
a947e83be9 Merge pull request #1870 from AiOO/bugfix/assertion-with-unicode
Fix UnicodeEncodeError when string comparison with unicode has failed.
2016-08-25 22:29:32 -03:00
Bruno Oliveira
e92d373460 Remove example of "monkeypatch" used in session scope
This is a leftover when invocation-scoped fixtures
were pulled back.

Fix #1872
2016-08-25 21:50:57 -03:00
Ahn Ki-Wook
86b8801470 Update AUTHORS and CHANGELOG 2016-08-26 09:42:17 +09:00
Ahn Ki-Wook
856ad719d3 Fix UnicodeEncodeError when string comparison with unicode has failed. 2016-08-26 09:41:40 +09:00
Ronny Pfannschmidt
9c45d6cd83 Merge pull request #1866 from joguSD/bugfix-stdin-stub-buffer
Add buffer attribute to DontReadFromInput
2016-08-25 07:07:44 +02:00
Jordan Guymon
a152ea2dbb Add buffer attribute to stdin stub 2016-08-24 16:26:34 -07:00
Raquel Alegre
8f516d27fa Moved import pkg_resources to else clause. 2016-08-24 10:25:01 +01:00
Florian Bruhin
3345ac9216 Merge pull request #1861 from nicoddemus/ids-invalid-type-msg
Improve error message when passing non-string ids to pytest.mark.parametrize
2016-08-24 06:43:57 +02:00
Bruno Oliveira
972a5fb5d5 Improve error message when passing non-string ids to pytest.mark.parametrize
Fix #1857
2016-08-23 23:31:45 -03:00
Bruno Oliveira
ea0febad28 Updates for new patch version 3.0.2 2016-08-23 21:33:57 -03:00
Bruno Oliveira
ecb20b96fc Merge pull request #1856 from nicoddemus/release-3.0.1
Changes for 3.0.1 release
2016-08-23 21:21:24 -03:00
Bruno Oliveira
49fc4e5e4c Changes for 3.0.1 release 2016-08-23 18:15:43 -04:00
Florian Bruhin
3c866e7080 Merge pull request #1855 from nicoddemus/fix-empty-parametrize-ids
Fix internal error when parametrizing using and empty list of ids()
2016-08-23 23:38:27 +02:00
Bruno Oliveira
df200297e2 Fix internal error when parametrizing using and empty list of ids()
Fix #1849
2016-08-23 18:18:46 -03:00
Ronny Pfannschmidt
7538680c98 Merge pull request #1847 from nicoddemus/parametrize-session-scopes
Fix code which guesses parametrized scope based on arguments
2016-08-23 18:03:52 +02:00
Raquel Alegre
d3f4b3d14a mend 2016-08-23 16:50:00 +01:00
Raquel Alegre
a1597aca89 Added #1853 to changelog as requested on PR. 2016-08-23 16:48:24 +01:00
Raquel Alegre
7d498fdc82 Added myself as AUTHOR as requested on PR. 2016-08-23 16:47:15 +01:00
Raquel Alegre
2f11a85698 Import pkg_resources only when necessary. 2016-08-23 16:41:11 +01:00
Bruno Oliveira
847067fb02 Merge pull request #1851 from adamchainz/deprecated_setup.cfg
Delete unreferenced setup.cfg from docs
2016-08-23 12:35:48 -03:00
Adam Chainz
1673667232 Delete unreferenced setup.cfg from docs
Noticed it's not using the new `[tool:pytest]` header as changed in #567, can't find any reference to it or `testfilepatterns`. It was added in b1e4301457 6 years ago, there don't seem to have ever been references to it.
2016-08-23 16:08:24 +01:00
Bruno Oliveira
53a0e2b118 Fix code which guesses parametrized scope based on arguments
Fix #1832
2016-08-22 21:05:41 -03:00
Bruno Oliveira
d99ceb1218 Merge pull request #1844 from nicoddemus/importer-error
Importer loader error
2016-08-22 20:47:25 -03:00
Bruno Oliveira
b54ea74d4d Update AUTHORS and CHANGELOG for #1837 2016-08-22 17:59:42 -03:00
Bruno Oliveira
6a8160b318 Add acceptance test for module loader
Related to #1837
2016-08-22 17:57:25 -03:00
Bruno Oliveira
c3148d1d6b Merge pull request #1842 from Stranger6667/doc-fix
Fix documentation
2016-08-22 14:11:36 -03:00
Bruno Oliveira
b0ede044ac Merge pull request #1835 from RonnyPfannschmidt/mark-extract-param
mark plugin: move the unclean marked parameter extraction
2016-08-22 14:11:11 -03:00
Dmitry Dygalo
3fbf2e7a80 Fix documentation 2016-08-22 18:38:02 +02:00
Florian Bruhin
af0ec120fe Merge pull request #1836 from asvetlov/patch-1
Remove duplicated name
2016-08-21 22:09:58 +02:00
Marcin Bachry
678750c8f8 Fix importer call 2016-08-21 22:07:18 +02:00
Andrew Svetlov
4e9c1fbe96 Remove duplicated name 2016-08-21 22:20:29 +03:00
Ronny Pfannschmidt
406777d104 mark plugin: move the unclean marked parameter extraction 2016-08-21 20:44:37 +02:00
Florian Bruhin
abe8f5e23f Merge pull request #1824 from nicoddemus/update-howtorelease
Update HOWTORELEASE based on the 3.0.0 release
2016-08-20 23:03:59 +02:00
Bruno Oliveira
6a0e849067 Update HOWTORELEASE based on the 3.0.0 release 2016-08-20 15:47:34 -03:00
Florian Bruhin
a20c3f9c44 Merge pull request #1827 from blueyed/Fix-spelling-s-outside-a-outside-of-a-
Fix spelling: s/outside a/outside of a/
2016-08-20 20:04:58 +02:00
Florian Bruhin
783aff17dd Merge pull request #1828 from blueyed/minor-s-no-pkg_resources-pkg_resources-
minor: s/no pkg_resources/pkg_resources/
2016-08-20 20:04:48 +02:00
Daniel Hahler
86ec3f37af minor: s/no pkg_resources/pkg_resources/ 2016-08-20 18:47:42 +02:00
Daniel Hahler
e306a53999 Fix spelling: s/outside a/outside of a/ 2016-08-20 18:43:39 +02:00
Florian Bruhin
90fb8cb08b Merge pull request #1823 from nicoddemus/importorskip-regression
Fix regression when using importorskip at module level
2016-08-20 18:37:14 +02:00
Bruno Oliveira
5129c2f867 Merge pull request #1826 from blueyed/Remove-duplicate-entry-for-#717-in-CHANGELOG
Remove duplicate entry for #717 in CHANGELOG
2016-08-20 11:21:53 -03:00
Daniel Hahler
87d2d1d838 Remove duplicate entry for #717 in CHANGELOG 2016-08-20 15:12:08 +02:00
Bruno Oliveira
9aec8d9a47 py.test team -> Pytest team :) 2016-08-19 18:59:13 -03:00
Bruno Oliveira
c8f53d6690 Fix typo in 3.0.0 release announcement 2016-08-19 18:58:14 -03:00
Bruno Oliveira
875bcd4224 Add 3.0.0 release announcement to index.rst 2016-08-19 18:30:11 -03:00
Bruno Oliveira
63dc71c57e Fix regression when using importorskip at module level
Fix #1822
2016-08-19 18:21:25 -03:00
Bruno Oliveira
3a200b75c9 Bump version to 3.0.1.dev 2016-08-19 17:41:45 -03:00
Bruno Oliveira
745c8c17f1 Merge remote-tracking branch 'upstream/master' 2016-08-19 17:38:21 -03:00
Bruno Oliveira
5ecf3d78f1 Merge pull request #1819 from matthiasha/patch-1
Documentation update for rootdir discovery
2016-08-19 17:36:44 -03:00
Bruno Oliveira
b85a3b0d71 Merge pull request #1820 from The-Compiler/changelog-duplicates
Remove duplicate CHANGELOG messages
2016-08-19 17:35:23 -03:00
Bruno Oliveira
8777f61e7b Merge pull request #1818 from nicoddemus/release-3.0
Release 3.0
2016-08-19 17:33:15 -03:00
Florian Bruhin
31ede2432c Remove duplicate CHANGELOG messages
Those are both already mentioned in the breaking changes at the top.
2016-08-19 17:05:02 +02:00
matthiasha
c8fbf3ae34 remove dot in pytest 2016-08-19 14:02:25 +02:00
matthiasha
3455dfc804 add missing @matthiasha link 2016-08-19 14:01:07 +02:00
matthiasha
cd39cc1eec Mention doc update in CHANGELOG 2016-08-19 09:08:11 +02:00
matthiasha
ccfa8d15bf Update AUTHORS 2016-08-19 09:04:19 +02:00
matthiasha
799dab9dba Documentation update for rootdir discovery
This covers issue https://github.com/pytest-dev/pytest/issues/1435.
2016-08-19 09:01:12 +02:00
163 changed files with 3433 additions and 1789 deletions

View File

@@ -3,6 +3,9 @@ Thanks for submitting a PR, your contribution is really appreciated!
Here's a quick checklist that should be present in PRs:
- [ ] Target: for bug or doc fixes, target `master`; for new features, target `features`;
Unless your change is trivial documentation fix (e.g., a typo or reword of a small section) please:
- [ ] Make sure to include one or more tests for your change;
- [ ] Add yourself to `AUTHORS`;
- [ ] Add a new entry to `CHANGELOG.rst`

View File

@@ -8,26 +8,37 @@ install: "pip install -U tox"
env:
matrix:
# coveralls is not listed in tox's envlist, but should run in travis
- TESTENV=coveralls
- TOXENV=coveralls
# note: please use "tox --listenvs" to populate the build matrix below
- TESTENV=linting
- TESTENV=py26
- TESTENV=py27
- TESTENV=py33
- TESTENV=py34
- TESTENV=py35
- TESTENV=pypy
- TESTENV=py27-pexpect
- TESTENV=py27-xdist
- TESTENV=py27-trial
- TESTENV=py35-pexpect
- TESTENV=py35-xdist
- TESTENV=py35-trial
- TESTENV=py27-nobyte
- TESTENV=doctesting
- TESTENV=freeze
- TOXENV=linting
- TOXENV=py26
- TOXENV=py27
- TOXENV=py33
- TOXENV=py34
- TOXENV=py35
- TOXENV=pypy
- TOXENV=py27-pexpect
- TOXENV=py27-xdist
- TOXENV=py27-trial
- TOXENV=py35-pexpect
- TOXENV=py35-xdist
- TOXENV=py35-trial
- TOXENV=py27-nobyte
- TOXENV=doctesting
- TOXENV=freeze
- TOXENV=docs
script: tox --recreate -e $TESTENV
matrix:
include:
- env: TOXENV=py36
python: '3.6-dev'
- env: TOXENV=py37
python: 'nightly'
allow_failures:
- env: TOXENV=py37
python: 'nightly'
script: tox --recreate
notifications:
irc:

27
AUTHORS
View File

@@ -5,6 +5,7 @@ Contributors include::
Abdeali JK
Abhijeet Kasurde
Ahn Ki-Wook
Alexei Kozlenok
Anatoly Bubenkoff
Andreas Zeidler
@@ -15,6 +16,7 @@ Antony Lee
Armin Rigo
Aron Curzon
Aviv Palivoda
Barney Gale
Ben Webb
Benjamin Peterson
Bernard Pratz
@@ -35,20 +37,23 @@ Christopher Gilling
Daniel Grana
Daniel Hahler
Daniel Nuri
Daniel Wandschneider
Danielle Jenkins
Dave Hunt
David Díaz-Barquero
David Mohr
David Vierra
Denis Kirisov
Diego Russo
Dmitry Dygalo
Duncan Betts
Edison Gustavo Muenz
Edoardo Batini
Eduardo Schettino
Eli Boyarski
Elizaveta Shashkova
Endre Galaczi
Eric Hunsberger
Eric Hunsberger
Eric Siegerman
Erik M. Bray
Feng Ma
@@ -59,6 +64,7 @@ Georgy Dyuldin
Graham Horler
Greg Price
Grig Gheorghiu
Grigorii Eremeev (budulianin)
Guido Wesdorp
Harald Armin Massa
Ian Bicking
@@ -68,8 +74,10 @@ Janne Vanhala
Jason R. Coombs
Javier Domingo Cansino
Javier Romero
Jeff Widman
John Towler
Jon Sonesen
Jordan Guymon
Joshua Bronson
Jurko Gospodnetić
Justyna Janczyszyn
@@ -77,31 +85,45 @@ Kale Kundert
Katarzyna Jachim
Kevin Cox
Lee Kamentsky
Lev Maximov
Loic Esteve
Lukas Bednar
Luke Murphy
Maciek Fijalkowski
Maho
Marc Schlaich
Marcin Bachry
Mark Abramowitz
Markus Unterwaditzer
Martijn Faassen
Martin K. Scherer
Martin Prusse
Mathieu Clabaut
Matt Bachmann
Matt Williams
Matthias Hafner
mbyt
Michael Aquilina
Michael Birtwell
Michael Droettboom
Michael Seifert
Mike Lundy
Ned Batchelder
Neven Mundar
Nicolas Delaby
Oleg Pidsadnyi
Oliver Bestwalter
Omar Kohl
Omer Hadari
Patrick Hayes
Pieter Mulder
Piotr Banaszkiewicz
Punyashloka Biswal
Quentin Pradet
Ralf Schmitt
Ran Benita
Raphael Pierzina
Raquel Alegre
Roberto Polli
Romain Dorgueil
Roman Bolshakov
@@ -121,6 +143,9 @@ Ted Xiao
Thomas Grainger
Tom Viner
Trevor Bekolay
Tyler Goodlet
Vasily Kuznetsov
Victor Uriarte
Vidar T. Fauske
Wouter van Ackooy
Xuecong Liao

File diff suppressed because it is too large Load Diff

View File

@@ -79,6 +79,16 @@ Pytest could always use more documentation. What exactly is needed?
You can also edit documentation files directly in the GitHub web interface,
without using a local copy. This can be convenient for small fixes.
.. note::
Build the documentation locally with the following command:
.. code:: bash
$ tox -e docs
The built documentation should be available in the ``doc/en/_build/``.
Where 'en' refers to the documentation language.
.. _submitplugin:
@@ -199,13 +209,10 @@ but here is a simple overview:
You need to have Python 2.7 and 3.5 available in your system. Now
running tests is as simple as issuing this command::
$ python3 runtox.py -e linting,py27,py35
$ tox -e linting,py27,py35
This command will run tests via the "tox" tool against Python 2.7 and 3.5
and also perform "lint" coding-style checks. ``runtox.py`` is
a thin wrapper around ``tox`` which installs from a development package
index where newer (not yet released to PyPI) versions of dependencies
(especially ``py``) might be present.
and also perform "lint" coding-style checks.
#. You can now edit your local working copy.
@@ -214,11 +221,11 @@ but here is a simple overview:
To run tests on Python 2.7 and pass options to pytest (e.g. enter pdb on
failure) to pytest you can do::
$ python3 runtox.py -e py27 -- --pdb
$ tox -e py27 -- --pdb
Or to only run tests in a particular test module on Python 3.5::
$ python3 runtox.py -e py35 -- testing/test_config.py
$ tox -e py35 -- testing/test_config.py
#. Commit and push once your tests pass and you are happy with your change(s)::

View File

@@ -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
- python-announce-list@python.org
- testing-in-python@lists.idyll.org (only for minor/major releases)
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.dev0"``.
3. Create a new section in ``CHANGELOG.rst`` titled ``2.8.4.dev0`` 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.dev0``.
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.dev0"``.
7. Create a new section in ``CHANGELOG.rst`` titled ``2.10.0.dev0``, above ``2.9.1.dev0``, 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

View File

@@ -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()

View File

@@ -4,31 +4,33 @@ include AUTHORS
include README.rst
include CONTRIBUTING.rst
include HOWTORELEASE.rst
include tox.ini
include setup.py
include .coveragerc
recursive-include scripts *.py
recursive-include scripts *.bat
include plugin-test.sh
include requirements-docs.txt
include runtox.py
include .coveragerc
recursive-include bench *.py
recursive-include extra *.py
graft testing
graft doc
prune doc/en/_build
exclude _pytest/impl
graft _pytest/vendored_packages
recursive-exclude * *.pyc *.pyo
recursive-exclude testing/.hypothesis *
recursive-exclude testing/freeze/~ *
recursive-exclude testing/freeze/build *
recursive-exclude testing/freeze/dist *
exclude appveyor/install.ps1
exclude appveyor.yml
exclude appveyor
exclude ISSUES.txt
exclude HOWTORELEASE.rst
exclude .travis.yml
prune .github

View File

@@ -24,35 +24,34 @@ An example of a simple test:
.. code-block:: python
# content of test_sample.py
def func(x):
def inc(x):
return x + 1
def test_answer():
assert func(3) == 5
assert inc(3) == 5
To execute it::
$ pytest
======= test session starts ========
platform linux -- Python 3.4.3, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
============================= test session starts =============================
collected 1 items
test_sample.py F
======= FAILURES ========
_______ test_answer ________
================================== FAILURES ===================================
_________________________________ test_answer _________________________________
def test_answer():
> assert func(3) == 5
> assert inc(3) == 5
E assert 4 == 5
E + where 4 = func(3)
E + where 4 = inc(3)
test_sample.py:5: AssertionError
======= 1 failed in 0.12 seconds ========
========================== 1 failed in 0.04 seconds ===========================
Due to ``py.test``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://docs.pytest.org/en/latest/getting-started.html#our-first-test-run>`_ for more examples.
Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://docs.pytest.org/en/latest/getting-started.html#our-first-test-run>`_ for more examples.
Features
@@ -64,7 +63,7 @@ Features
<http://docs.pytest.org/en/latest/goodpractices.html#python-test-discovery>`_
of test modules and functions;
- `Modular fixtures <http://docs.pytest.org/en/latest/fixture.html>`_ for
- `Modular fixtures <http://docs.pytest.org/en/latest/fixture.html>`_ for
managing small or parametrized long-lived test resources;
- Can run `unittest <http://docs.pytest.org/en/latest/unittest.html>`_ (or trial),
@@ -90,7 +89,7 @@ Please use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issue
Changelog
---------
Consult the `Changelog <http://docs.pytest.org/en/latest/changelog.html>`_ page for fixes and enhancements of each version.
Consult the `Changelog <http://docs.pytest.org/en/latest/changelog.html>`__ page for fixes and enhancements of each version.
License

View File

@@ -1,2 +1,2 @@
#
__version__ = '3.0.0'
__version__ = '3.0.7'

View File

@@ -87,6 +87,7 @@ class FastFilesCompleter:
completion.append(x[prefix_dir:])
return completion
if os.environ.get('_ARGCOMPLETE'):
try:
import argcomplete.completers

View File

@@ -1,6 +1,7 @@
import sys
from inspect import CO_VARARGS, CO_VARKEYWORDS
import re
from weakref import ref
import py
builtin_repr = repr
@@ -12,6 +13,7 @@ if sys.version_info[0] >= 3:
else:
from ._py2traceback import format_exception_only
class Code(object):
""" wrapper around Python code objects """
def __init__(self, rawcode):
@@ -28,6 +30,8 @@ class Code(object):
def __eq__(self, other):
return self.raw == other.raw
__hash__ = None
def __ne__(self, other):
return not self == other
@@ -227,7 +231,7 @@ class TracebackEntry(object):
return False
if py.builtin.callable(tbh):
return tbh(self._excinfo)
return tbh(None if self._excinfo is None else self._excinfo())
else:
return tbh
@@ -339,6 +343,7 @@ class Traceback(list):
l.append(entry.frame.f_locals)
return None
co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
'?', 'eval')
@@ -347,6 +352,8 @@ class ExceptionInfo(object):
help for navigating the traceback.
"""
_striptext = ''
_assert_start_repr = "AssertionError(u\'assert " if sys.version_info[0] < 3 else "AssertionError(\'assert "
def __init__(self, tup=None, exprinfo=None):
import _pytest._code
if tup is None:
@@ -354,8 +361,8 @@ class ExceptionInfo(object):
if exprinfo is None and isinstance(tup[1], AssertionError):
exprinfo = getattr(tup[1], 'msg', None)
if exprinfo is None:
exprinfo = str(tup[1])
if exprinfo and exprinfo.startswith('assert '):
exprinfo = py.io.saferepr(tup[1])
if exprinfo and exprinfo.startswith(self._assert_start_repr):
self._striptext = 'AssertionError: '
self._excinfo = tup
#: the exception class
@@ -367,7 +374,7 @@ class ExceptionInfo(object):
#: the exception type name
self.typename = self.type.__name__
#: the exception traceback (_pytest._code.Traceback instance)
self.traceback = _pytest._code.Traceback(self.tb, excinfo=self)
self.traceback = _pytest._code.Traceback(self.tb, excinfo=ref(self))
def __repr__(self):
return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
@@ -620,16 +627,23 @@ class FormattedExcinfo(object):
e = excinfo.value
descr = None
while e is not None:
reprtraceback = self.repr_traceback(excinfo)
reprcrash = excinfo._getreprcrash()
if excinfo:
reprtraceback = self.repr_traceback(excinfo)
reprcrash = excinfo._getreprcrash()
else:
# fallback to native repr if the exception doesn't have a traceback:
# ExceptionInfo objects require a full traceback to work
reprtraceback = ReprTracebackNative(py.std.traceback.format_exception(type(e), e, None))
reprcrash = None
repr_chain += [(reprtraceback, reprcrash, descr)]
if e.__cause__ is not None:
e = e.__cause__
excinfo = ExceptionInfo((type(e), e, e.__traceback__))
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
descr = 'The above exception was the direct cause of the following exception:'
elif e.__context__ is not None:
e = e.__context__
excinfo = ExceptionInfo((type(e), e, e.__traceback__))
excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
descr = 'During handling of the above exception, another exception occurred:'
else:
e = None
@@ -835,6 +849,7 @@ def getrawcode(obj, trycall=True):
return x
return obj
if sys.version_info[:2] >= (3, 5): # RecursionError introduced in 3.5
def is_recursion_error(excinfo):
return excinfo.errisinstance(RecursionError) # noqa

View File

@@ -4,7 +4,6 @@ from bisect import bisect_right
import sys
import inspect, tokenize
import py
from types import ModuleType
cpy_compile = compile
try:
@@ -52,22 +51,21 @@ class Source(object):
return str(self) == other
return False
__hash__ = None
def __getitem__(self, key):
if isinstance(key, int):
return self.lines[key]
else:
if key.step not in (None, 1):
raise IndexError("cannot slice a Source with a step")
return self.__getslice__(key.start, key.stop)
newsource = Source()
newsource.lines = self.lines[key.start:key.stop]
return newsource
def __len__(self):
return len(self.lines)
def __getslice__(self, start, end):
newsource = Source()
newsource.lines = self.lines[start:end]
return newsource
def strip(self):
""" return new source object with trailing
and leading blank lines removed.
@@ -193,14 +191,6 @@ class Source(object):
if flag & _AST_FLAG:
return co
lines = [(x + "\n") for x in self.lines]
if sys.version_info[0] >= 3:
# XXX py3's inspect.getsourcefile() checks for a module
# and a pep302 __loader__ ... we don't have a module
# at code compile-time so we need to fake it here
m = ModuleType("_pycodecompile_pseudo_module")
py.std.inspect.modulesbyfile[filename] = None
py.std.sys.modules[None] = m
m.__loader__ = 1
py.std.linecache.cache[filename] = (1, None, lines, filename)
return co
@@ -266,6 +256,7 @@ def findsource(obj):
source.lines = [line.rstrip() for line in sourcelines]
return source, lineno
def getsource(obj, **kwargs):
import _pytest._code
obj = _pytest._code.getrawcode(obj)
@@ -276,6 +267,7 @@ def getsource(obj, **kwargs):
assert isinstance(strsrc, str)
return Source(strsrc, **kwargs)
def deindent(lines, offset=None):
if offset is None:
for line in lines:
@@ -289,6 +281,7 @@ def deindent(lines, offset=None):
if offset == 0:
return list(lines)
newlines = []
def readline_generator(lines):
for line in lines:
yield line + '\n'

View File

@@ -29,14 +29,20 @@ def pytest_namespace():
def register_assert_rewrite(*names):
"""Register a module name to be rewritten on import.
"""Register one or more module names to be rewritten on import.
This function will make sure that this module or all modules inside
the package will get their assert statements rewritten.
Thus you should make sure to call this before the module is
actually imported, usually in your __init__.py if you are a plugin
using a package.
:raise TypeError: if the given module names are not strings.
"""
for name in names:
if not isinstance(name, str):
msg = 'expected module names as *args, got {0} instead'
raise TypeError(msg.format(repr(names)))
for hook in sys.meta_path:
if isinstance(hook, rewrite.AssertionRewritingHook):
importhook = hook
@@ -74,10 +80,12 @@ def install_importhook(config):
config._assertstate.hook = hook = rewrite.AssertionRewritingHook(config)
sys.meta_path.insert(0, hook)
config._assertstate.trace('installed rewrite import hook')
def undo():
hook = config._assertstate.hook
if hook is not None and hook in sys.meta_path:
sys.meta_path.remove(hook)
config.add_cleanup(undo)
return hook

View File

@@ -51,6 +51,7 @@ class AssertionRewritingHook(object):
self.fnpats = config.getini("python_files")
self.session = None
self.modules = {}
self._rewritten_names = set()
self._register_with_pkg_resources()
self._must_rewrite = set()
@@ -79,7 +80,12 @@ class AssertionRewritingHook(object):
tp = desc[2]
if tp == imp.PY_COMPILED:
if hasattr(imp, "source_from_cache"):
fn = imp.source_from_cache(fn)
try:
fn = imp.source_from_cache(fn)
except ValueError:
# Python 3 doesn't like orphaned but still-importable
# .pyc files.
fn = fn[:-1]
else:
fn = fn[:-1]
elif tp != imp.PY_SOURCE:
@@ -92,6 +98,8 @@ class AssertionRewritingHook(object):
if not self._should_rewrite(name, fn_pypath, state):
return None
self._rewritten_names.add(name)
# The requested module looks like a test file, so rewrite it. This is
# the most magical part of the process: load the source, rewrite the
# asserts, and load the rewritten source. We also cache the rewritten
@@ -178,14 +186,15 @@ class AssertionRewritingHook(object):
"""
already_imported = set(names).intersection(set(sys.modules))
if already_imported:
self._warn_already_imported(already_imported)
for name in already_imported:
if name not in self._rewritten_names:
self._warn_already_imported(name)
self._must_rewrite.update(names)
def _warn_already_imported(self, names):
def _warn_already_imported(self, name):
self.config.warn(
'P1',
'Modules are already imported so can not be re-written: %s' %
','.join(names))
'Module already imported so can not be re-written: %s' % name)
def load_module(self, name):
# If there is an existing module object named 'fullname' in
@@ -206,7 +215,8 @@ class AssertionRewritingHook(object):
mod.__loader__ = self
py.builtin.exec_(co, mod.__dict__)
except:
del sys.modules[name]
if name in sys.modules:
del sys.modules[name]
raise
return sys.modules[name]
@@ -271,6 +281,7 @@ def _write_pyc(state, co, source_stat, pyc):
fp.close()
return True
RN = "\r\n".encode("utf-8")
N = "\n".encode("utf-8")

View File

@@ -105,7 +105,7 @@ except NameError:
def assertrepr_compare(config, op, left, right):
"""Return specialised explanations for some operators/operands"""
width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
left_repr = py.io.saferepr(left, maxsize=int(width/2))
left_repr = py.io.saferepr(left, maxsize=int(width//2))
right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
summary = u('%s %s %s') % (ecu(left_repr), op, ecu(right_repr))

View File

@@ -1,7 +1,7 @@
"""
merged implementation of the cache provider
the name cache was not choosen to ensure pluggy automatically
the name cache was not chosen to ensure pluggy automatically
ignores the external pytest-cache
"""

View File

@@ -152,6 +152,7 @@ class CaptureManager:
item.add_report_section(when, "stdout", out)
item.add_report_section(when, "stderr", err)
error_capsysfderror = "cannot use capsys and capfd at the same time"
@@ -455,6 +456,13 @@ class DontReadFromInput:
def close(self):
pass
@property
def buffer(self):
if sys.version_info >= (3,0):
return self
else:
raise AttributeError('redirected stdin has no attribute buffer')
def _readline_workaround():
"""

View File

@@ -19,6 +19,7 @@ except ImportError: # pragma: no cover
# Only available in Python 3.4+ or as a backport
enum = None
_PY3 = sys.version_info > (3, 0)
_PY2 = not _PY3
@@ -26,6 +27,9 @@ _PY2 = not _PY3
NoneType = type(None)
NOTSET = object()
PY36 = sys.version_info[:2] >= (3, 6)
MODULE_NOT_FOUND_ERROR = 'ModuleNotFoundError' if PY36 else 'ImportError'
if hasattr(inspect, 'signature'):
def _format_args(func):
return str(inspect.signature(func))
@@ -42,11 +46,18 @@ REGEX_TYPE = type(re.compile(''))
def is_generator(func):
try:
return _pytest._code.getrawcode(func).co_flags & 32 # generator function
except AttributeError: # builtin functions have no bytecode
# assume them to not be generators
return False
genfunc = inspect.isgeneratorfunction(func)
return genfunc and not iscoroutinefunction(func)
def iscoroutinefunction(func):
"""Return True if func is a decorated coroutine function.
Note: copied and modified from Python 3.5's builtin couroutines.py to avoid import asyncio directly,
which in turns also initializes the "logging" module as side-effect (see issue #8).
"""
return (getattr(func, '_is_coroutine', False) or
(hasattr(inspect, 'iscoroutinefunction') and inspect.iscoroutinefunction(func)))
def getlocation(function, curdir):
@@ -213,4 +224,18 @@ def _is_unittest_unexpected_success_a_failure():
Changed in version 3.4: Returns False if there were any
unexpectedSuccesses from tests marked with the expectedFailure() decorator.
"""
return sys.version_info >= (3, 4)
return sys.version_info >= (3, 4)
if _PY3:
def safe_str(v):
"""returns v as string"""
return str(v)
else:
def safe_str(v):
"""returns v as string, converting to ascii if necessary"""
try:
return str(v)
except UnicodeError:
errors = 'replace'
return v.encode('ascii', errors)

View File

@@ -5,7 +5,6 @@ import traceback
import types
import warnings
import pkg_resources
import py
# DON't import pytest here because it causes import cycle troubles
import sys, os
@@ -13,6 +12,7 @@ import _pytest._code
import _pytest.hookspec # the extension point definitions
import _pytest.assertion
from _pytest._pluggy import PluginManager, HookimplMarker, HookspecMarker
from _pytest.compat import safe_str
hookimpl = HookimplMarker("pytest")
hookspec = HookspecMarker("pytest")
@@ -65,9 +65,33 @@ def main(args=None, plugins=None):
class cmdline: # compatibility namespace
main = staticmethod(main)
class UsageError(Exception):
""" error in pytest usage or invocation"""
def filename_arg(path, optname):
""" Argparse type validator for filename arguments.
:path: path of filename
:optname: name of the option
"""
if os.path.isdir(path):
raise UsageError("{0} must be a filename, given: {1}".format(optname, path))
return path
def directory_arg(path, optname):
"""Argparse type validator for directory arguments.
:path: path of directory
:optname: name of the option
"""
if not os.path.isdir(path):
raise UsageError("{0} must be a directory, given: {1}".format(optname, path))
return path
_preinit = []
default_plugins = (
@@ -378,33 +402,30 @@ class PytestPluginManager(PluginManager):
self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
def consider_module(self, mod):
plugins = getattr(mod, 'pytest_plugins', [])
self.rewrite_hook.mark_rewrite(*plugins)
self._import_plugin_specs(plugins)
self._import_plugin_specs(getattr(mod, 'pytest_plugins', []))
def _import_plugin_specs(self, spec):
if spec:
if isinstance(spec, str):
spec = spec.split(",")
for import_spec in spec:
self.import_plugin(import_spec)
plugins = _get_plugin_specs_as_list(spec)
for import_spec in plugins:
self.import_plugin(import_spec)
def import_plugin(self, modname):
# most often modname refers to builtin modules, e.g. "pytester",
# "terminal" or "capture". Those plugins are registered under their
# basename for historic purposes but must be imported with the
# _pytest prefix.
assert isinstance(modname, str)
assert isinstance(modname, str), "module name as string required, got %r" % modname
if self.get_plugin(modname) is not None:
return
if modname in builtin_plugins:
importspec = "_pytest." + modname
else:
importspec = modname
self.rewrite_hook.mark_rewrite(importspec)
try:
__import__(importspec)
except ImportError as e:
new_exc = ImportError('Error importing plugin "%s": %s' % (modname, e))
new_exc = ImportError('Error importing plugin "%s": %s' % (modname, safe_str(e.args[0])))
# copy over name and path attributes
for attr in ('name', 'path'):
if hasattr(e, attr):
@@ -421,6 +442,24 @@ class PytestPluginManager(PluginManager):
self.consider_module(mod)
def _get_plugin_specs_as_list(specs):
"""
Parses a list of "plugin specs" and returns a list of plugin names.
Plugin specs can be given as a list of strings separated by "," or already as a list/tuple in
which case it is returned as a list. Specs can also be `None` in which case an
empty list is returned.
"""
if specs is not None:
if isinstance(specs, str):
specs = specs.split(',') if specs else []
if not isinstance(specs, (list, tuple)):
raise UsageError("Plugin specs must be a ','-separated string or a "
"list/tuple of strings for plugin names. Given: %r" % specs)
return list(specs)
return []
class Parser:
""" Parser for command line arguments and ini-file values.
@@ -592,7 +631,7 @@ class Argument:
if typ == 'choice':
warnings.warn(
'type argument to addoption() is a string %r.'
' For parsearg this is optional and when supplied '
' For parsearg this is optional and when supplied'
' should be a type.'
' (options: %s)' % (typ, names),
DeprecationWarning,
@@ -791,7 +830,7 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter):
if len(option) == 2 or option[2] == ' ':
return_list.append(option)
if option[2:] == short_long.get(option.replace('-', '')):
return_list.append(option.replace(' ', '='))
return_list.append(option.replace(' ', '=', 1))
action._formatted_action_invocation = ', '.join(return_list)
return action._formatted_action_invocation
@@ -816,9 +855,11 @@ class Notset:
def __repr__(self):
return "<NOTSET>"
notset = Notset()
FILE_OR_DIR = 'file_or_dir'
class Config(object):
""" access to configuration values, pluginmanager and plugin hooks. """
@@ -836,14 +877,17 @@ class Config(object):
self.trace = self.pluginmanager.trace.root.get("config")
self.hook = self.pluginmanager.hook
self._inicache = {}
self._override_ini = ()
self._opt2dest = {}
self._cleanup = []
self._warn = self.pluginmanager._warn
self.pluginmanager.register(self, "pytestconfig")
self._configured = False
def do_setns(dic):
import pytest
setns(pytest, dic)
self.hook.pytest_namespace.call_historic(do_setns, {})
self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
@@ -934,6 +978,7 @@ class Config(object):
self.invocation_dir = py.path.local()
self._parser.addini('addopts', 'extra command line options', 'args')
self._parser.addini('minversion', 'minimally required pytest version')
self._override_ini = ns.override_ini or ()
def _consider_importhook(self, args, entrypoint_name):
"""Install the PEP 302 import hook if using assertion re-writing.
@@ -950,18 +995,24 @@ class Config(object):
except SystemError:
mode = 'plain'
else:
import pkg_resources
self.pluginmanager.rewrite_hook = hook
for entrypoint in pkg_resources.iter_entry_points('pytest11'):
for entry in entrypoint.dist._get_metadata('RECORD'):
fn = entry.split(',')[0]
is_simple_module = os.sep not in fn and fn.endswith('.py')
is_package = fn.count(os.sep) == 1 and fn.endswith('__init__.py')
if is_simple_module:
module_name, ext = os.path.splitext(fn)
hook.mark_rewrite(module_name)
elif is_package:
package_name = os.path.dirname(fn)
hook.mark_rewrite(package_name)
# 'RECORD' available for plugins installed normally (pip install)
# 'SOURCES.txt' available for plugins installed in dev mode (pip install -e)
# for installed plugins 'SOURCES.txt' returns an empty list, and vice-versa
# so it shouldn't be an issue
for metadata in ('RECORD', 'SOURCES.txt'):
for entry in entrypoint.dist._get_metadata(metadata):
fn = entry.split(',')[0]
is_simple_module = os.sep not in fn and fn.endswith('.py')
is_package = fn.count(os.sep) == 1 and fn.endswith('__init__.py')
if is_simple_module:
module_name, ext = os.path.splitext(fn)
hook.mark_rewrite(module_name)
elif is_package:
package_name = os.path.dirname(fn)
hook.mark_rewrite(package_name)
self._warn_about_missing_assertion(mode)
def _warn_about_missing_assertion(self, mode):
@@ -993,6 +1044,7 @@ class Config(object):
self.pluginmanager.load_setuptools_entrypoints(entrypoint_name)
self.pluginmanager.consider_env()
self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
confcutdir = self.known_args_namespace.confcutdir
if self.known_args_namespace.confcutdir is None and self.inifile:
confcutdir = py.path.local(self.inifile).dirname
self.known_args_namespace.confcutdir = confcutdir
@@ -1109,12 +1161,14 @@ class Config(object):
# and -o foo1=bar1 -o foo2=bar2 options
# always use the last item if multiple value set for same ini-name,
# e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2
if self.getoption("override_ini", None):
for ini_config_list in self.option.override_ini:
for ini_config in ini_config_list:
for ini_config_list in self._override_ini:
for ini_config in ini_config_list:
try:
(key, user_ini_value) = ini_config.split("=", 1)
if key == name:
value = user_ini_value
except ValueError:
raise UsageError("-o/--override-ini expects option=value style.")
if key == name:
value = user_ini_value
return value
def getoption(self, name, default=notset, skip=False):
@@ -1188,25 +1242,20 @@ def getcfg(args, warnfunc=None):
return None, None, None
def get_common_ancestor(args):
# args are what we get after early command line parsing (usually
# strings, but can be py.path.local objects as well)
def get_common_ancestor(paths):
common_ancestor = None
for arg in args:
if str(arg)[0] == "-":
continue
p = py.path.local(arg)
if not p.exists():
for path in paths:
if not path.exists():
continue
if common_ancestor is None:
common_ancestor = p
common_ancestor = path
else:
if p.relto(common_ancestor) or p == common_ancestor:
if path.relto(common_ancestor) or path == common_ancestor:
continue
elif common_ancestor.relto(p):
common_ancestor = p
elif common_ancestor.relto(path):
common_ancestor = path
else:
shared = p.common(common_ancestor)
shared = path.common(common_ancestor)
if shared is not None:
common_ancestor = shared
if common_ancestor is None:
@@ -1217,9 +1266,29 @@ def get_common_ancestor(args):
def get_dirs_from_args(args):
return [d for d in (py.path.local(x) for x in args
if not str(x).startswith("-"))
if d.exists()]
def is_option(x):
return str(x).startswith('-')
def get_file_part_from_node_id(x):
return str(x).split('::')[0]
def get_dir_from_path(path):
if path.isdir():
return path
return py.path.local(path.dirname)
# These look like paths but may not exist
possible_paths = (
py.path.local(get_file_part_from_node_id(arg))
for arg in args
if not is_option(arg)
)
return [
get_dir_from_path(path)
for path in possible_paths
if path.exists()
]
def determine_setup(inifile, args, warnfunc=None):

View File

@@ -14,7 +14,7 @@ def pytest_addoption(parser):
group._addoption(
'--pdbcls', dest="usepdb_cls", metavar="modulename:classname",
help="start a custom interactive Python debugger on errors. "
"For example: --pdbcls=IPython.core.debugger:Pdb")
"For example: --pdbcls=IPython.terminal.debugger:TerminalPdb")
def pytest_namespace():
return {'set_trace': pytestPDB().set_trace}
@@ -31,10 +31,12 @@ def pytest_configure(config):
pytestPDB._pdb_cls = pdb_cls
old = (pdb.set_trace, pytestPDB._pluginmanager)
def fin():
pdb.set_trace, pytestPDB._pluginmanager = old
pytestPDB._config = None
pytestPDB._pdb_cls = pdb.Pdb
pdb.set_trace = pytest.set_trace
pytestPDB._pluginmanager = config.pluginmanager
pytestPDB._config = config

View File

@@ -88,7 +88,7 @@ class DoctestItem(pytest.Item):
if self.dtest is not None:
self.fixture_request = _setup_fixtures(self)
globs = dict(getfixture=self.fixture_request.getfixturevalue)
for name, value in self.fixture_request.getfuncargvalue('doctest_namespace').items():
for name, value in self.fixture_request.getfixturevalue('doctest_namespace').items():
globs[name] = value
self.dtest.globs.update(globs)

View File

@@ -14,6 +14,7 @@ from _pytest.compat import (
getfslineno, get_real_func,
is_generator, isclass, getimfunc,
getlocation, getfuncargnames,
safe_getattr,
)
def pytest_sessionstart(session):
@@ -32,11 +33,13 @@ scope2props["function"] = scope2props["instance"] + ("function", "keywords")
def scopeproperty(name=None, doc=None):
def decoratescope(func):
scopename = name or func.__name__
def provide(self):
if func.__name__ in scope2props[self.scope]:
return func(self)
raise AttributeError("%s not available in %s-scoped context" % (
scopename, self.scope))
return property(provide, None, None, func.__doc__)
return decoratescope
@@ -122,8 +125,6 @@ def getfixturemarker(obj):
exceptions."""
try:
return getattr(obj, "_pytestfixturefunction", None)
except KeyboardInterrupt:
raise
except Exception:
# some objects raise errors like request (from flask import request)
# we don't expect them to be fixture functions
@@ -599,12 +600,29 @@ class ScopeMismatchError(Exception):
which has a lower scope (e.g. a Session one calls a function one)
"""
scopes = "session module class function".split()
scopenum_function = scopes.index("function")
def scopemismatch(currentscope, newscope):
return scopes.index(newscope) > scopes.index(currentscope)
def scope2index(scope, descr, where=None):
"""Look up the index of ``scope`` and raise a descriptive value error
if not defined.
"""
try:
return scopes.index(scope)
except ValueError:
raise ValueError(
"{0} {1}has an unsupported scope value '{2}'".format(
descr, 'from {0} '.format(where) if where else '',
scope)
)
class FixtureLookupError(LookupError):
""" could not return a requested Fixture (missing or invalid). """
def __init__(self, argname, request, msg=None):
@@ -703,6 +721,7 @@ def call_fixture_func(fixturefunc, request, kwargs):
res = fixturefunc(**kwargs)
return res
class FixtureDef:
""" A container for a factory definition. """
def __init__(self, fixturemanager, baseid, argname, func, scope, params,
@@ -713,7 +732,11 @@ class FixtureDef:
self.func = func
self.argname = argname
self.scope = scope
self.scopenum = scopes.index(scope or "function")
self.scopenum = scope2index(
scope or "function",
descr='fixture {0}'.format(func.__name__),
where=baseid
)
self.params = params
startindex = unittest and 1 or None
self.argnames = getfuncargnames(func, startindex=startindex)
@@ -1044,7 +1067,9 @@ class FixtureManager:
self._holderobjseen.add(holderobj)
autousenames = []
for name in dir(holderobj):
obj = getattr(holderobj, name, None)
# The attribute can be an arbitrary descriptor, so the attribute
# access below can raise. safe_getatt() ignores such exceptions.
obj = safe_getattr(holderobj, name, None)
# fixture functions have a pytest_funcarg__ prefix (pre-2.3 style)
# or are "@pytest.fixture" marked
marker = getfixturemarker(obj)

View File

@@ -23,7 +23,7 @@ def pytest_addoption(parser):
group._addoption(
'-o', '--override-ini', nargs='*', dest="override_ini",
action="append",
help="override config option, e.g. `-o xfail_strict=True`.")
help="override config option with option=value style, e.g. `-o xfail_strict=True`.")
@pytest.hookimpl(hookwrapper=True)
@@ -41,12 +41,14 @@ def pytest_cmdline_parse():
config.trace.root.setwriter(debugfile.write)
undo_tracing = config.pluginmanager.enable_tracing()
sys.stderr.write("writing pytestdebug information to %s\n" % path)
def unset_tracing():
debugfile.close()
sys.stderr.write("wrote pytestdebug information to %s\n" %
debugfile.name)
config.trace.root.setwriter(None)
undo_tracing()
config.add_cleanup(unset_tracing)
def pytest_cmdline_main(config):
@@ -71,8 +73,8 @@ def showhelp(config):
tw.write(config._parser.optparser.format_help())
tw.line()
tw.line()
tw.line("[pytest] ini-options in the next "
"pytest.ini|tox.ini|setup.cfg file:")
tw.line("[pytest] ini-options in the first "
"pytest.ini|tox.ini|setup.cfg file found:")
tw.line()
for name in config._parser._ininames:

View File

@@ -246,7 +246,7 @@ def pytest_unconfigure(config):
# -------------------------------------------------------------------------
# hooks for customising the assert methods
# hooks for customizing the assert methods
# -------------------------------------------------------------------------
def pytest_assertrepr_compare(config, op, left, right):
@@ -255,7 +255,7 @@ def pytest_assertrepr_compare(config, op, left, right):
Return None for no custom explanation, otherwise return a list
of strings. The strings will be joined by newlines but any newlines
*in* a string will be escaped. Note that all but the first line will
be indented sligthly, the intention is for the first line to be a summary.
be indented slightly, the intention is for the first line to be a summary.
"""
# -------------------------------------------------------------------------
@@ -263,7 +263,14 @@ def pytest_assertrepr_compare(config, op, left, right):
# -------------------------------------------------------------------------
def pytest_report_header(config, startdir):
""" return a string to be displayed as header info for terminal reporting."""
""" return a string to be displayed as header info for terminal reporting.
.. note::
This function should be implemented only in plugins or ``conftest.py``
files situated at the tests root directory due to how pytest
:ref:`discovers plugins during startup <pluginorder>`.
"""
@hookspec(firstresult=True)
def pytest_report_teststatus(report):

View File

@@ -8,12 +8,14 @@ Based on initial code from Ross Lawley.
# Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
# src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
import functools
import py
import os
import re
import sys
import time
import pytest
from _pytest.config import filename_arg
# Python 2.X and 3.X compatibility
if sys.version_info[0] < 3:
@@ -27,6 +29,7 @@ else:
class Junit(py.xml.Namespace):
pass
# We need to get the subset of the invalid unicode ranges according to
# XML 1.0 which are valid in this python build. Hence we calculate
# this dynamically instead of hardcoding it. The spec range of valid
@@ -116,7 +119,7 @@ class _NodeReporter(object):
node = kind(data, message=message)
self.append(node)
def _write_captured_output(self, report):
def write_captured_output(self, report):
for capname in ('out', 'err'):
content = getattr(report, 'capstd' + capname)
if content:
@@ -125,7 +128,6 @@ class _NodeReporter(object):
def append_pass(self, report):
self.add_stats('passed')
self._write_captured_output(report)
def append_failure(self, report):
# msg = str(report.longrepr.reprtraceback.extraline)
@@ -144,7 +146,6 @@ class _NodeReporter(object):
fail = Junit.failure(message=message)
fail.append(bin_xml_escape(report.longrepr))
self.append(fail)
self._write_captured_output(report)
def append_collect_error(self, report):
# msg = str(report.longrepr.reprtraceback.extraline)
@@ -156,9 +157,12 @@ class _NodeReporter(object):
Junit.skipped, "collection skipped", report.longrepr)
def append_error(self, report):
if getattr(report, 'when', None) == 'teardown':
msg = "test teardown failure"
else:
msg = "test setup failure"
self._add_simple(
Junit.error, "test setup failure", report.longrepr)
self._write_captured_output(report)
Junit.error, msg, report.longrepr)
def append_skipped(self, report):
if hasattr(report, "wasxfail"):
@@ -173,7 +177,7 @@ class _NodeReporter(object):
Junit.skipped("%s:%s: %s" % (filename, lineno, skipreason),
type="pytest.skip",
message=skipreason))
self._write_captured_output(report)
self.write_captured_output(report)
def finalize(self):
data = self.to_xml().unicode(indent=0)
@@ -209,6 +213,7 @@ def pytest_addoption(parser):
action="store",
dest="xmlpath",
metavar="path",
type=functools.partial(filename_arg, optname="--junitxml"),
default=None,
help="create junit-xml style report file at given path.")
group.addoption(
@@ -337,6 +342,8 @@ class LogXML(object):
reporter.append_skipped(report)
self.update_testcase_duration(report)
if report.when == "teardown":
reporter = self._opentestcase(report)
reporter.write_captured_output(report)
self.finalize(report)
def update_testcase_duration(self, report):

View File

@@ -1,4 +1,5 @@
""" core implementation of testing process: init, session, runtest loop. """
import functools
import os
import sys
@@ -11,6 +12,7 @@ try:
except ImportError:
from UserDict import DictMixin as MappingMixin
from _pytest.config import directory_arg
from _pytest.runner import collect_one_node
tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
@@ -58,7 +60,7 @@ def pytest_addoption(parser):
# when changing this to --conf-cut-dir, config.py Conftest.setinitial
# needs upgrading as well
group.addoption('--confcutdir', dest="confcutdir", default=None,
metavar="dir",
metavar="dir", type=functools.partial(directory_arg, optname="--confcutdir"),
help="only load conftest.py's relative to specified dir.")
group.addoption('--noconftest', action="store_true",
dest="noconftest", default=False,
@@ -79,7 +81,7 @@ def pytest_namespace():
def pytest_configure(config):
pytest.config = config # compatibiltiy
pytest.config = config # compatibility
def wrap_session(config, doit):
@@ -188,12 +190,22 @@ class FSHookProxy:
self.__dict__[name] = x
return x
def compatproperty(name):
def fget(self):
# deprecated - use pytest.name
return getattr(pytest, name)
class _CompatProperty(object):
def __init__(self, name):
self.name = name
def __get__(self, obj, owner):
if obj is None:
return self
# TODO: reenable in the features branch
# warnings.warn(
# "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format(
# name=self.name, owner=type(owner).__name__),
# PendingDeprecationWarning, stacklevel=2)
return getattr(pytest, self.name)
return property(fget)
class NodeKeywords(MappingMixin):
def __init__(self, node):
@@ -265,19 +277,23 @@ class Node(object):
""" fspath sensitive hook proxy used to call pytest hooks"""
return self.session.gethookproxy(self.fspath)
Module = compatproperty("Module")
Class = compatproperty("Class")
Instance = compatproperty("Instance")
Function = compatproperty("Function")
File = compatproperty("File")
Item = compatproperty("Item")
Module = _CompatProperty("Module")
Class = _CompatProperty("Class")
Instance = _CompatProperty("Instance")
Function = _CompatProperty("Function")
File = _CompatProperty("File")
Item = _CompatProperty("Item")
def _getcustomclass(self, name):
cls = getattr(self, name)
if cls != getattr(pytest, name):
py.log._apiwarn("2.0", "use of node.%s is deprecated, "
"use pytest_pycollect_makeitem(...) to create custom "
"collection nodes" % name)
maybe_compatprop = getattr(type(self), name)
if isinstance(maybe_compatprop, _CompatProperty):
return getattr(pytest, name)
else:
cls = getattr(self, name)
# TODO: reenable in the features branch
# warnings.warn("use of node.%s is deprecated, "
# "use pytest_pycollect_makeitem(...) to create custom "
# "collection nodes" % name, category=DeprecationWarning)
return cls
def __repr__(self):
@@ -535,7 +551,6 @@ class Session(FSCollector):
def __init__(self, config):
FSCollector.__init__(self, config.rootdir, parent=None,
config=config, session=self)
self._fs2hookproxy = {}
self.testsfailed = 0
self.testscollected = 0
self.shouldstop = False
@@ -566,23 +581,18 @@ class Session(FSCollector):
return path in self._initialpaths
def gethookproxy(self, fspath):
try:
return self._fs2hookproxy[fspath]
except KeyError:
# check if we have the common case of running
# hooks with all conftest.py filesall conftest.py
pm = self.config.pluginmanager
my_conftestmodules = pm._getconftestmodules(fspath)
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
if remove_mods:
# one or more conftests are not in use at this fspath
proxy = FSHookProxy(fspath, pm, remove_mods)
else:
# all plugis are active for this fspath
proxy = self.config.hook
self._fs2hookproxy[fspath] = proxy
return proxy
# check if we have the common case of running
# hooks with all conftest.py filesall conftest.py
pm = self.config.pluginmanager
my_conftestmodules = pm._getconftestmodules(fspath)
remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
if remove_mods:
# one or more conftests are not in use at this fspath
proxy = FSHookProxy(fspath, pm, remove_mods)
else:
# all plugis are active for this fspath
proxy = self.config.hook
return proxy
def perform_collect(self, args=None, genitems=True):
hook = self.config.hook
@@ -687,7 +697,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
@@ -704,10 +714,9 @@ class Session(FSCollector):
path = self.config.invocation_dir.join(relpath, abs=True)
if not path.check():
if self.config.option.pyargs:
msg = "file or package not found: "
raise pytest.UsageError("file or package not found: " + arg + " (missing __init__.py?)")
else:
msg = "file not found: "
raise pytest.UsageError(msg + arg)
raise pytest.UsageError("file not found: " + arg)
parts[0] = path
return parts

View File

@@ -19,7 +19,7 @@ def pytest_addoption(parser):
help="only run tests which match the given substring expression. "
"An expression is a python evaluatable expression "
"where all names are substring-matched against test names "
"and their parent classes. Example: -k 'test_method or test "
"and their parent classes. Example: -k 'test_method or test_"
"other' matches all test functions and classes whose name "
"contains 'test_method' or 'test_other'. "
"Additionally keywords are matched to classes and functions "
@@ -54,6 +54,8 @@ def pytest_cmdline_main(config):
tw.line()
config._ensure_unconfigure()
return 0
pytest_cmdline_main.tryfirst = True
@@ -64,7 +66,7 @@ def pytest_collection_modifyitems(items, config):
return
# pytest used to allow "-" for negating
# but today we just allow "-" at the beginning, use "not" instead
# we probably remove "-" alltogether soon
# we probably remove "-" altogether soon
if keywordexpr.startswith("-"):
keywordexpr = "not " + keywordexpr[1:]
selectuntil = False
@@ -283,6 +285,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):

View File

@@ -11,7 +11,7 @@ RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$")
@pytest.fixture
def monkeypatch(request):
def monkeypatch():
"""The returned ``monkeypatch`` fixture provides these
helper methods to modify objects, dictionaries or os.environ::
@@ -30,8 +30,8 @@ def monkeypatch(request):
will be raised if the set/deletion operation has no target.
"""
mpatch = MonkeyPatch()
request.addfinalizer(mpatch.undo)
return mpatch
yield mpatch
mpatch.undo()
def resolve(name):

View File

@@ -11,6 +11,7 @@ def pytest_addoption(parser):
choices=['failed', 'all'],
help="send failed|all info to bpaste.net pastebin service.")
@pytest.hookimpl(trylast=True)
def pytest_configure(config):
import py
@@ -23,13 +24,16 @@ def pytest_configure(config):
# pastebin file will be utf-8 encoded binary file
config._pastebinfile = tempfile.TemporaryFile('w+b')
oldwrite = tr._tw.write
def tee_write(s, **kwargs):
oldwrite(s, **kwargs)
if py.builtin._istext(s):
s = s.encode('utf-8')
config._pastebinfile.write(s)
tr._tw.write = tee_write
def pytest_unconfigure(config):
if hasattr(config, '_pastebinfile'):
# get terminal contents and delete file
@@ -45,6 +49,7 @@ def pytest_unconfigure(config):
pastebinurl = create_new_paste(sessionlog)
tr.write_line("pastebin session-log: %s\n" % pastebinurl)
def create_new_paste(contents):
"""
Creates a new paste using bpaste.net service.
@@ -72,6 +77,7 @@ def create_new_paste(contents):
else:
return 'bad response: ' + response
def pytest_terminal_summary(terminalreporter):
import _pytest.config
if terminalreporter.config.option.pastebin != "failed":

View File

@@ -332,7 +332,7 @@ def testdir(request, tmpdir_factory):
return Testdir(request, tmpdir_factory)
rex_outcome = re.compile("(\d+) ([\w-]+)")
rex_outcome = re.compile(r"(\d+) ([\w-]+)")
class RunResult:
"""The result of running a command.
@@ -367,6 +367,7 @@ class RunResult:
for num, cat in outcomes:
d[cat] = int(num)
return d
raise ValueError("Pytest terminal report not found")
def assert_outcomes(self, passed=0, skipped=0, failed=0):
""" assert that the specified outcomes appear with the respective
@@ -446,9 +447,9 @@ class Testdir:
the module is re-imported.
"""
for name in set(sys.modules).difference(self._savemodulekeys):
# it seems zope.interfaces is keeping some state
# (used by twisted related tests)
if name != "zope.interface":
# zope.interface (used by twisted-related tests) keeps internal
# state and can't be deleted
if not name.startswith("zope.interface"):
del sys.modules[name]
def make_hook_recorder(self, pluginmanager):
@@ -478,11 +479,14 @@ class Testdir:
ret = None
for name, value in items:
p = self.tmpdir.join(name).new(ext=ext)
p.dirpath().ensure_dir()
source = Source(value)
def my_totext(s, encoding="utf-8"):
if py.builtin._isbytes(s):
s = py.builtin._totext(s, encoding=encoding)
return s
source_unicode = "\n".join([my_totext(line) for line in source.lines])
source = py.builtin._totext(source_unicode)
content = source.strip().encode("utf-8") # + "\n"
@@ -562,7 +566,7 @@ class Testdir:
def mkpydir(self, name):
"""Create a new python package.
This creates a (sub)direcotry with an empty ``__init__.py``
This creates a (sub)directory with an empty ``__init__.py``
file so that is recognised as a python package.
"""
@@ -657,7 +661,7 @@ class Testdir:
def inline_genitems(self, *args):
"""Run ``pytest.main(['--collectonly'])`` in-process.
Retuns a tuple of the collected items and a
Returns a tuple of the collected items and a
:py:class:`HookRecorder` instance.
This runs the :py:func:`pytest.main` function to run all of
@@ -692,12 +696,15 @@ class Testdir:
# warning which will trigger to say they can no longer be
# re-written, which is fine as they are already re-written.
orig_warn = AssertionRewritingHook._warn_already_imported
def revert():
AssertionRewritingHook._warn_already_imported = orig_warn
self.request.addfinalizer(revert)
AssertionRewritingHook._warn_already_imported = lambda *a: None
rec = []
class Collect:
def pytest_configure(x, config):
rec.append(self.make_hook_recorder(config.pluginmanager))
@@ -732,10 +739,13 @@ class Testdir:
try:
reprec = self.inline_run(*args, **kwargs)
except SystemExit as e:
class reprec:
ret = e.args[0]
except Exception:
traceback.print_exc()
class reprec:
ret = 3
finally:
@@ -847,7 +857,7 @@ class Testdir:
:py:meth:`parseconfigure`.
:param withinit: Whether to also write a ``__init__.py`` file
to the temporarly directory to ensure it is a package.
to the temporary directory to ensure it is a package.
"""
kw = {self.request.function.__name__: Source(source).strip()}
@@ -1002,8 +1012,6 @@ class Testdir:
pexpect = pytest.importorskip("pexpect", "3.0")
if hasattr(sys, 'pypy_version_info') and '64' in platform.machine():
pytest.skip("pypy-64 bit not supported")
if sys.platform == "darwin":
pytest.xfail("pexpect does not work reliably on darwin?!")
if sys.platform.startswith("freebsd"):
pytest.xfail("pexpect does not work reliably on freebsd")
logfile = self.tmpdir.join("spawn.out").open("wb")

View File

@@ -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
@@ -21,11 +22,16 @@ from _pytest.compat import (
getlocation, enum,
)
cutdir2 = py.path.local(_pytest.__file__).dirpath()
cutdir1 = py.path.local(pluggy.__file__.rstrip("oc"))
cutdir2 = py.path.local(_pytest.__file__).dirpath()
cutdir3 = py.path.local(py.__file__).dirpath()
def filter_traceback(entry):
"""Return True if a TracebackEntry instance should be removed from tracebacks:
* dynamically generated code (no code to show up for it);
* internal traceback from pytest or its internal libraries, py and pluggy.
"""
# entry.path might sometimes return a str object when the entry
# points to dynamically generated code
# see https://bitbucket.org/pytest-dev/py/issues/71
@@ -36,7 +42,7 @@ def filter_traceback(entry):
# entry.path might point to an inexisting file, in which case it will
# alsso return a str object. see #1133
p = py.path.local(entry.path)
return p != cutdir1 and not p.relto(cutdir2)
return p != cutdir1 and not p.relto(cutdir2) and not p.relto(cutdir3)
@@ -168,7 +174,7 @@ def pytest_pycollect_makeitem(collector, name, obj):
outcome = yield
res = outcome.get_result()
if res is not None:
raise StopIteration
return
# nothing was collected elsewhere, let's do it here
if isclass(obj):
if collector.istestclass(obj, name):
@@ -204,14 +210,16 @@ class PyobjContext(object):
class PyobjMixin(PyobjContext):
def obj():
def fget(self):
try:
return self._obj
except AttributeError:
obj = getattr(self, '_obj', None)
if obj is None:
self._obj = obj = self._getobj()
return obj
return obj
def fset(self, value):
self._obj = value
return property(fget, fset, None, "underlying python object")
obj = obj()
def _getobj(self):
@@ -424,18 +432,25 @@ class Module(pytest.File, PyCollector):
% e.args
)
except ImportError:
exc_class, exc, _ = sys.exc_info()
from _pytest._code.code import ExceptionInfo
exc_info = ExceptionInfo()
if self.config.getoption('verbose') < 2:
exc_info.traceback = exc_info.traceback.filter(filter_traceback)
exc_repr = exc_info.getrepr(style='short') if exc_info.traceback else exc_info.exconly()
formatted_tb = py._builtin._totext(exc_repr)
raise self.CollectError(
"ImportError while importing test module '%s'.\n"
"Original error message:\n'%s'\n"
"Make sure your test modules/packages have valid Python names."
% (self.fspath, exc or exc_class)
"ImportError while importing test module '{fspath}'.\n"
"Hint: make sure your test modules/packages have valid Python names.\n"
"Traceback:\n"
"{traceback}".format(fspath=self.fspath, traceback=formatted_tb)
)
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 "
"@pytest.mark.skipif instead."
"Using pytest.skip outside of a test is not allowed. If you are "
"trying to decorate a test function, use the @pytest.mark.skip "
"or @pytest.mark.skipif decorators instead."
)
self.config.pluginmanager.consider_module(mod)
return mod
@@ -614,7 +629,7 @@ class Generator(FunctionMixin, PyCollector):
def getcallargs(self, obj):
if not isinstance(obj, (tuple, list)):
obj = (obj,)
# explict naming
# explicit naming
if isinstance(obj[0], py.builtin._basestring):
name = obj[0]
obj = obj[1:]
@@ -708,31 +723,26 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
They help to inspect a test function and to generate tests according to
test configuration or values specified in the class or module where a
test function is defined.
:ivar fixturenames: set of fixture names required by the test function
:ivar function: underlying python test function
:ivar cls: class object where the test function is defined in or ``None``.
:ivar module: the module object where the test function is defined in.
:ivar config: access to the :class:`_pytest.config.Config` object for the
test session.
:ivar funcargnames:
.. deprecated:: 2.3
Use ``fixturenames`` instead.
"""
def __init__(self, function, fixtureinfo, config, cls=None, module=None):
#: access to the :class:`_pytest.config.Config` object for the test session
self.config = config
#: the module object where the test function is defined in.
self.module = module
#: underlying python test function
self.function = function
#: set of fixture names required by the test function
self.fixturenames = fixtureinfo.names_closure
self._arg2fixturedefs = fixtureinfo.name2fixturedefs
#: class object where the test function is defined in or ``None``.
self.cls = cls
self._calls = []
self._ids = py.builtin.set()
self._arg2fixturedefs = fixtureinfo.name2fixturedefs
def parametrize(self, argnames, argvalues, indirect=False, ids=None,
scope=None):
@@ -773,20 +783,16 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
It will also override any fixture-function defined scope, allowing
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.fixtures import scope2index
from _pytest.mark import extract_argvalue
from py.io import saferepr
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,19 +807,13 @@ 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'
scopenum = scopes.index(scope)
scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
scopenum = scope2index(
scope, descr='call to {0}'.format(self.parametrize))
valtypes = {}
for arg in argnames:
if arg not in self.fixturenames:
@@ -840,18 +840,23 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
if callable(ids):
idfn = ids
ids = None
if ids and len(ids) != len(argvalues):
raise ValueError('%d tests specified with %d ids' %(
len(argvalues), len(ids)))
if ids:
if len(ids) != len(argvalues):
raise ValueError('%d tests specified with %d ids' %(
len(argvalues), len(ids)))
for id_value in ids:
if id_value is not None and not isinstance(id_value, py.builtin._basestring):
msg = 'ids must be list of strings, found: %s (type: %s)'
raise ValueError(msg % (saferepr(id_value), type(id_value).__name__))
ids = idmaker(argnames, argvalues, idfn, ids, self.config)
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 +897,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 +950,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)
@@ -1079,7 +1108,9 @@ def raises(expected_exception, *args, **kwargs):
>>> with raises(ZeroDivisionError, message="Expecting ZeroDivisionError"):
... pass
... Failed: Expecting ZeroDivisionError
Traceback (most recent call last):
...
Failed: Expecting ZeroDivisionError
.. note::
@@ -1090,19 +1121,21 @@ def raises(expected_exception, *args, **kwargs):
Lines of code after that, within the scope of the context manager will
not be executed. For example::
>>> with raises(OSError) as exc_info:
assert 1 == 1 # this will execute as expected
raise OSError(errno.EEXISTS, 'directory exists')
assert exc_info.value.errno == errno.EEXISTS # this will not execute
>>> value = 15
>>> with raises(ValueError) as exc_info:
... if value > 10:
... raise ValueError("value must be <= 10")
... assert str(exc_info.value) == "value must be <= 10" # this will not execute
Instead, the following approach must be taken (note the difference in
scope)::
>>> with raises(OSError) as exc_info:
assert 1 == 1 # this will execute as expected
raise OSError(errno.EEXISTS, 'directory exists')
>>> with raises(ValueError) as exc_info:
... if value > 10:
... raise ValueError("value must be <= 10")
...
>>> assert str(exc_info.value) == "value must be <= 10"
assert exc_info.value.errno == errno.EEXISTS # this will now execute
Or you can specify a callable by passing a to-be-called lambda::
@@ -1207,7 +1240,11 @@ class RaisesContext(object):
exc_type, value, traceback = tp
tp = exc_type, exc_type(value), traceback
self.excinfo.__init__(tp)
return issubclass(self.excinfo.type, self.expected_exception)
suppress_exception = issubclass(self.excinfo.type, self.expected_exception)
if sys.version_info[0] == 2 and suppress_exception:
sys.exc_clear()
return suppress_exception
# builtin pytest.approx helper
@@ -1341,6 +1378,8 @@ class approx(object):
return False
return all(a == x for a, x in zip(actual, self.expected))
__hash__ = None
def __ne__(self, actual):
return not (actual == self)
@@ -1380,6 +1419,9 @@ class ApproxNonIterable(object):
self.rel = rel
def __repr__(self):
if isinstance(self.expected, complex):
return str(self.expected)
# Infinities aren't compared using tolerances, so don't show a
# tolerance.
if math.isinf(self.expected):
@@ -1392,16 +1434,10 @@ class ApproxNonIterable(object):
except ValueError:
vetted_tolerance = '???'
plus_minus = u'{0} \u00b1 {1}'.format(self.expected, vetted_tolerance)
# In python2, __repr__() must return a string (i.e. not a unicode
# object). In python3, __repr__() must return a unicode object
# (although now strings are unicode objects and bytes are what
# strings were).
if sys.version_info[0] == 2:
return plus_minus.encode('utf-8')
return '{0} +- {1}'.format(self.expected, vetted_tolerance)
else:
return plus_minus
return u'{0} \u00b1 {1}'.format(self.expected, vetted_tolerance)
def __eq__(self, actual):
# Short-circuit exact equality.
@@ -1420,6 +1456,8 @@ class ApproxNonIterable(object):
# Return true if the two numbers are within the tolerance.
return abs(self.expected - actual) <= self.tolerance
__hash__ = None
def __ne__(self, actual):
return not (actual == self)

View File

@@ -36,8 +36,13 @@ def deprecated_call(func=None, *args, **kwargs):
This function can be used as a context manager::
>>> import warnings
>>> def api_call_v2():
... warnings.warn('use v3 of this api', DeprecationWarning)
... return 200
>>> with deprecated_call():
... myobject.deprecated_method()
... assert api_call_v2() == 200
Note: we cannot use WarningsRecorder here because it is still subject
to the mechanism that prevents warnings of the same type from being
@@ -218,4 +223,7 @@ class WarningsChecker(WarningsRecorder):
if self.expected_warning is not None:
if not any(r.category in self.expected_warning for r in self):
__tracebackhide__ = True
pytest.fail("DID NOT WARN")
pytest.fail("DID NOT WARN. No warnings of type {0} was emitted. "
"The list of emitted warnings is: {1}.".format(
self.expected_warning,
[each.message for each in self]))

View File

@@ -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"):
@@ -509,8 +515,10 @@ def exit(msg):
__tracebackhide__ = True
raise Exit(msg)
exit.Exception = Exit
def skip(msg=""):
""" skip an executing test with the given message. Note: it's usually
better to use the pytest.mark.skipif marker to declare a test to be
@@ -519,8 +527,11 @@ def skip(msg=""):
"""
__tracebackhide__ = True
raise Skipped(msg=msg)
skip.Exception = Skipped
def fail(msg="", pytrace=True):
""" explicitly fail an currently-executing test with the given Message.
@@ -529,6 +540,8 @@ def fail(msg="", pytrace=True):
"""
__tracebackhide__ = True
raise Failed(msg=msg, pytrace=pytrace)
fail.Exception = Failed
@@ -546,7 +559,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 +568,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

View File

@@ -5,9 +5,9 @@ import sys
def pytest_addoption(parser):
group = parser.getgroup("debugconfig")
group.addoption('--setuponly', '--setup-only', action="store_true",
help="only setup fixtures, don't execute the tests.")
help="only setup fixtures, do not execute tests.")
group.addoption('--setupshow', '--setup-show', action="store_true",
help="show setup fixtures while executing the tests.")
help="show setup of fixtures while executing tests.")
@pytest.hookimpl(hookwrapper=True)

View File

@@ -25,8 +25,10 @@ def pytest_configure(config):
if config.option.runxfail:
old = pytest.xfail
config._cleanup.append(lambda: setattr(pytest, "xfail", old))
def nop(*args, **kwargs):
pass
nop.Exception = XFailed
setattr(pytest, "xfail", nop)
@@ -44,7 +46,7 @@ def pytest_configure(config):
)
config.addinivalue_line("markers",
"xfail(condition, reason=None, run=True, raises=None, strict=False): "
"mark the the test function as an expected failure if eval(condition) "
"mark the test function as an expected failure if eval(condition) "
"has a True value. Optionally specify a reason for better reporting "
"and run=False if you don't even want to execute the test function. "
"If only specific exception(s) are expected, you can list them in "
@@ -65,6 +67,8 @@ def xfail(reason=""):
""" xfail an executing test or setup functions with the given reason."""
__tracebackhide__ = True
raise XFailed(reason)
xfail.Exception = XFailed
@@ -108,14 +112,14 @@ class MarkEvaluator:
def _getglobals(self):
d = {'os': os, 'sys': sys, 'config': self.item.config}
d.update(self.item.obj.__globals__)
if hasattr(self.item, 'obj'):
d.update(self.item.obj.__globals__)
return d
def _istrue(self):
if hasattr(self, 'result'):
return self.result
if self.holder:
d = self._getglobals()
if self.holder.args or 'condition' in self.holder.kwargs:
self.result = False
# "holder" might be a MarkInfo or a MarkDecorator; only
@@ -131,6 +135,7 @@ class MarkEvaluator:
for expr in args:
self.expr = expr
if isinstance(expr, py.builtin._basestring):
d = self._getglobals()
result = cached_eval(self.item.config, expr, d)
else:
if "reason" not in kwargs:

View File

@@ -295,8 +295,8 @@ class TerminalReporter:
def pytest_report_header(self, config):
inifile = ""
if config.inifile:
inifile = config.rootdir.bestrelpath(config.inifile)
lines = ["rootdir: %s, inifile: %s" %(config.rootdir, inifile)]
inifile = " " + config.rootdir.bestrelpath(config.inifile)
lines = ["rootdir: %s, inifile:%s" % (config.rootdir, inifile)]
plugininfo = config.pluginmanager.list_plugin_distinfo()
if plugininfo:
@@ -458,6 +458,15 @@ class TerminalReporter:
self.write_sep("_", msg)
self._outrep_summary(rep)
def print_teardown_sections(self, rep):
for secname, content in rep.sections:
if 'teardown' in secname:
self._tw.sep('-', secname)
if content[-1:] == "\n":
content = content[:-1]
self._tw.line(content)
def summary_failures(self):
if self.config.option.tbstyle != "no":
reports = self.getreports('failed')
@@ -473,6 +482,9 @@ class TerminalReporter:
markup = {'red': True, 'bold': True}
self.write_sep("_", msg, **markup)
self._outrep_summary(rep)
for report in self.getreports(''):
if report.nodeid == rep.nodeid and report.when == 'teardown':
self.print_teardown_sections(report)
def summary_errors(self):
if self.config.option.tbstyle != "no":

View File

@@ -81,6 +81,7 @@ def get_user():
except (ImportError, KeyError):
return None
# backward compatibility
TempdirHandler = TempdirFactory
@@ -115,7 +116,7 @@ def tmpdir(request, tmpdir_factory):
path object.
"""
name = request.node.name
name = re.sub("[\W]", "_", name)
name = re.sub(r"[\W]", "_", name)
MAXVAL = 30
if len(name) > MAXVAL:
name = name[:MAXVAL]

View File

@@ -5,7 +5,7 @@ import sys
import traceback
import pytest
# for transfering markers
# for transferring markers
import _pytest._code
from _pytest.python import transfer_markers
from _pytest.skipping import MarkEvaluator
@@ -65,7 +65,6 @@ class UnitTestCase(pytest.Class):
yield TestCaseFunction('runTest', parent=self)
class TestCaseFunction(pytest.Function):
_excinfo = None
@@ -94,6 +93,9 @@ class TestCaseFunction(pytest.Function):
def teardown(self):
if hasattr(self._testcase, 'teardown_method'):
self._testcase.teardown_method(self._obj)
# Allow garbage collection on TestCase instance attributes.
self._testcase = None
self._obj = None
def startTest(self, testcase):
pass
@@ -149,8 +151,32 @@ class TestCaseFunction(pytest.Function):
def stopTest(self, testcase):
pass
def _handle_skip(self):
# implements the skipping machinery (see #2137)
# analog to pythons Lib/unittest/case.py:run
testMethod = getattr(self._testcase, self._testcase._testMethodName)
if (getattr(self._testcase.__class__, "__unittest_skip__", False) or
getattr(testMethod, "__unittest_skip__", False)):
# If the class or method was skipped.
skip_why = (getattr(self._testcase.__class__, '__unittest_skip_why__', '') or
getattr(testMethod, '__unittest_skip_why__', ''))
try: # PY3, unittest2 on PY2
self._testcase._addSkip(self, self._testcase, skip_why)
except TypeError: # PY2
if sys.version_info[0] != 2:
raise
self._testcase._addSkip(self, skip_why)
return True
return False
def runtest(self):
self._testcase(result=self)
if self.config.pluginmanager.get_plugin("pdbinvoke") is None:
self._testcase(result=self)
else:
# disables tearDown and cleanups for post mortem debugging (see #1890)
if self._handle_skip():
return
self._testcase.debug()
def _prunetraceback(self, excinfo):
pytest.Function._prunetraceback(self, excinfo)
@@ -178,6 +204,7 @@ def pytest_runtest_protocol(item):
ut = sys.modules['twisted.python.failure']
Failure__init__ = ut.Failure.__init__
check_testcase_implements_trial_reporter()
def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
captureVars=None):
if exc_value is None:
@@ -191,6 +218,7 @@ def pytest_runtest_protocol(item):
captureVars=captureVars)
except TypeError:
Failure__init__(self, exc_value, exc_type, exc_tb)
ut.Failure.__init__ = excstore
yield
ut.Failure.__init__ = Failure__init__

View File

@@ -10,4 +10,4 @@ $ pip install -U pluggy==<version> --no-compile --target=_pytest/vendored_packag
```
And commit the modified files. The `pluggy-<version>.dist-info` directory
created by `pip` should be ignored.
created by `pip` should be added as well.

View File

@@ -1,8 +0,0 @@
pluggy.py,sha256=v_RfWzyW6DPU1cJu_EFoL_OHq3t13qloVdR6UaMCXQA,29862
pluggy-0.3.1.dist-info/top_level.txt,sha256=xKSCRhai-v9MckvMuWqNz16c1tbsmOggoMSwTgcpYHE,7
pluggy-0.3.1.dist-info/pbr.json,sha256=xX3s6__wOcAyF-AZJX1sdZyW6PUXT-FkfBlM69EEUCg,47
pluggy-0.3.1.dist-info/RECORD,,
pluggy-0.3.1.dist-info/metadata.json,sha256=nLKltOT78dMV-00uXD6Aeemp4xNsz2q59j6ORSDeLjw,1027
pluggy-0.3.1.dist-info/METADATA,sha256=1b85Ho2u4iK30M099k7axMzcDDhLcIMb-A82JUJZnSo,1334
pluggy-0.3.1.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110
pluggy-0.3.1.dist-info/DESCRIPTION.rst,sha256=P5Akh1EdIBR6CeqtV2P8ZwpGSpZiTKPw0NyS7jEiD-g,306

View File

@@ -1 +0,0 @@
{"license": "MIT license", "name": "pluggy", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "plugin and hook calling mechanisms for python", "platform": "unix", "version": "0.3.1", "extensions": {"python.details": {"document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "holger at merlinux.eu", "name": "Holger Krekel"}]}}, "classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Testing", "Topic :: Software Development :: Libraries", "Topic :: Utilities", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5"]}

View File

@@ -1 +0,0 @@
{"is_release": false, "git_version": "7d4c9cd"}

View File

@@ -1,3 +1,4 @@
Plugin registration and hook calling for Python
===============================================

View File

@@ -0,0 +1 @@
pip

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 holger krekel (rather uses bitbucket/hpk42)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,8 +1,8 @@
Metadata-Version: 2.0
Name: pluggy
Version: 0.3.1
Version: 0.4.0
Summary: plugin and hook calling mechanisms for python
Home-page: UNKNOWN
Home-page: https://github.com/pytest-dev/pluggy
Author: Holger Krekel
Author-email: holger at merlinux.eu
License: MIT license
@@ -27,6 +27,7 @@ Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Plugin registration and hook calling for Python
===============================================

View File

@@ -0,0 +1,9 @@
pluggy.py,sha256=u0oG9cv-oLOkNvEBlwnnu8pp1AyxpoERgUO00S3rvpQ,31543
pluggy-0.4.0.dist-info/DESCRIPTION.rst,sha256=ltvjkFd40LW_xShthp6RRVM6OB_uACYDFR3kTpKw7o4,307
pluggy-0.4.0.dist-info/LICENSE.txt,sha256=ruwhUOyV1HgE9F35JVL9BCZ9vMSALx369I4xq9rhpkM,1134
pluggy-0.4.0.dist-info/METADATA,sha256=pe2hbsqKFaLHC6wAQPpFPn0KlpcPfLBe_BnS4O70bfk,1364
pluggy-0.4.0.dist-info/RECORD,,
pluggy-0.4.0.dist-info/WHEEL,sha256=9Z5Xm-eel1bTS7e6ogYiKz0zmPEqDwIypurdHN1hR40,116
pluggy-0.4.0.dist-info/metadata.json,sha256=T3go5L2qOa_-H-HpCZi3EoVKb8sZ3R-fOssbkWo2nvM,1119
pluggy-0.4.0.dist-info/top_level.txt,sha256=xKSCRhai-v9MckvMuWqNz16c1tbsmOggoMSwTgcpYHE,7
pluggy-0.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4

View File

@@ -1,5 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.24.0)
Generator: bdist_wheel (0.29.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View File

@@ -0,0 +1 @@
{"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Testing", "Topic :: Software Development :: Libraries", "Topic :: Utilities", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5"], "extensions": {"python.details": {"contacts": [{"email": "holger at merlinux.eu", "name": "Holger Krekel", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "https://github.com/pytest-dev/pluggy"}}}, "generator": "bdist_wheel (0.29.0)", "license": "MIT license", "metadata_version": "2.0", "name": "pluggy", "platform": "unix", "summary": "plugin and hook calling mechanisms for python", "version": "0.4.0"}

View File

@@ -67,8 +67,9 @@ Pluggy currently consists of functionality for:
import sys
import inspect
__version__ = '0.3.1'
__all__ = ["PluginManager", "PluginValidationError",
__version__ = '0.4.0'
__all__ = ["PluginManager", "PluginValidationError", "HookCallError",
"HookspecMarker", "HookimplMarker"]
_py3 = sys.version_info > (3, 0)
@@ -308,7 +309,7 @@ class PluginManager(object):
""" Core Pluginmanager class which manages registration
of plugin objects and 1:N hook calling.
You can register new hooks by calling ``addhooks(module_or_class)``.
You can register new hooks by calling ``add_hookspec(module_or_class)``.
You can register plugin objects (which contain hooks) by calling
``register(plugin)``. The Pluginmanager is initialized with a
prefix that is searched for in the names of the dict of registered
@@ -374,7 +375,10 @@ class PluginManager(object):
def parse_hookimpl_opts(self, plugin, name):
method = getattr(plugin, name)
res = getattr(method, self.project_name + "_impl", None)
try:
res = getattr(method, self.project_name + "_impl", None)
except Exception:
res = {}
if res is not None and not isinstance(res, dict):
# false positive
res = None
@@ -455,6 +459,10 @@ class PluginManager(object):
""" Return a plugin or None for the given name. """
return self._name2plugin.get(name)
def has_plugin(self, name):
""" Return True if a plugin with the given name is registered. """
return self.get_plugin(name) is not None
def get_name(self, plugin):
""" Return name for registered plugin or None if not registered. """
for name, val in self._name2plugin.items():
@@ -492,7 +500,8 @@ class PluginManager(object):
def load_setuptools_entrypoints(self, entrypoint_name):
""" Load modules from querying the specified setuptools entrypoint name.
Return the number of loaded plugins. """
from pkg_resources import iter_entry_points, DistributionNotFound
from pkg_resources import (iter_entry_points, DistributionNotFound,
VersionConflict)
for ep in iter_entry_points(entrypoint_name):
# is the plugin registered or blocked?
if self.get_plugin(ep.name) or self.is_blocked(ep.name):
@@ -501,6 +510,9 @@ class PluginManager(object):
plugin = ep.load()
except DistributionNotFound:
continue
except VersionConflict as e:
raise PluginValidationError(
"Plugin %r could not be loaded: %s!" % (ep.name, e))
self.register(plugin, name=ep.name)
self._plugin_distinfo.append((plugin, ep.dist))
return len(self._plugin_distinfo)
@@ -573,7 +585,7 @@ class _MultiCall:
# XXX note that the __multicall__ argument is supported only
# for pytest compatibility reasons. It was never officially
# supported there and is explicitly deprecated since 2.8
# supported there and is explicitely deprecated since 2.8
# so we can remove it soon, allowing to avoid the below recursion
# in execute() and simplify/speed up the execute loop.
@@ -590,7 +602,13 @@ class _MultiCall:
while self.hook_impls:
hook_impl = self.hook_impls.pop()
args = [all_kwargs[argname] for argname in hook_impl.argnames]
try:
args = [all_kwargs[argname] for argname in hook_impl.argnames]
except KeyError:
for argname in hook_impl.argnames:
if argname not in all_kwargs:
raise HookCallError(
"hook call must provide argument %r" % (argname,))
if hook_impl.hookwrapper:
return _wrapped_call(hook_impl.function(*args), self.execute)
res = hook_impl.function(*args)
@@ -629,7 +647,10 @@ def varnames(func, startindex=None):
startindex = 1
else:
if not inspect.isfunction(func) and not inspect.ismethod(func):
func = getattr(func, '__call__', func)
try:
func = getattr(func, '__call__', func)
except Exception:
return ()
if startindex is None:
startindex = int(inspect.ismethod(func))
@@ -763,6 +784,10 @@ class PluginValidationError(Exception):
""" plugin failed validation. """
class HookCallError(Exception):
""" Hook was called wrongly. """
if hasattr(inspect, 'signature'):
def _formatdef(func):
return "%s%s" % (

View File

@@ -6,30 +6,37 @@ environment:
# 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,freeze"
# coveralls is not in the default env list
- TOXENV: "coveralls"
# note: please use "tox --listenvs" to populate the build matrix below
- TOXENV: "linting"
- TOXENV: "py26"
- TOXENV: "py27"
- TOXENV: "py33"
- TOXENV: "py34"
- TOXENV: "py35"
- TOXENV: "py36"
- TOXENV: "pypy"
- TOXENV: "py27-pexpect"
- TOXENV: "py27-xdist"
- TOXENV: "py27-trial"
- TOXENV: "py35-pexpect"
- TOXENV: "py35-xdist"
- TOXENV: "py35-trial"
- TOXENV: "py27-nobyte"
- TOXENV: "doctesting"
- TOXENV: "freeze"
- TOXENV: "docs"
install:
- echo Installed Pythons
- dir c:\Python*
# install pypy using choco (redirect to a file and write to console in case
# choco install returns non-zero, because choco install python.pypy is too
# noisy)
- choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1)
- set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy
- echo PyPy installed
- pypy --version
- if "%TOXENV%" == "pypy" call scripts\install-pypy.bat
- C:\Python35\python -m pip install tox
build: false # Not a C# project, build stuff at the test step instead.
test_script:
- C:\Python35\python -m tox
# coveralls is not in tox's envlist, plus for PRs the secure variable
# is not defined so we have to check for it
- if defined COVERALLS_REPO_TOKEN C:\Python35\python -m tox -e coveralls
- call scripts\call-tox.bat

View File

@@ -19,10 +19,9 @@ REGENDOC_ARGS := \
--normalize "@/tmp/pytest-of-.*/pytest-\d+@PYTEST_TMPDIR@" \
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@@ -36,22 +35,6 @@ help:
clean:
-rm -rf $(BUILDDIR)/*
SITETARGET=$(shell ./_getdoctarget.py)
showtarget:
@echo $(SITETARGET)
install: html
# for access talk to someone with login rights to
# pytest-dev@pytest.org to add your ssh key
rsync -avz _build/html/ pytest-dev@pytest.org:pytest.org/$(SITETARGET)
installpdf: latexpdf
@scp $(BUILDDIR)/latex/pytest.pdf pytest-dev@pytest.org:pytest.org/$(SITETARGET)
installall: clean install installpdf
@echo "done"
regen:
PYTHONDONTWRITEBYTECODE=1 COLUMNS=76 regendoc --update *.rst */*.rst ${REGENDOC_ARGS}

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env python
import py
def get_version_string():
fn = py.path.local(__file__).join("..", "..", "..",
"_pytest", "__init__.py")
for line in fn.readlines():
if "version" in line and not line.strip().startswith('#'):
return eval(line.split("=")[-1])
def get_minor_version_string():
return ".".join(get_version_string().split(".")[:2])
if __name__ == "__main__":
print (get_minor_version_string())

View File

@@ -6,6 +6,6 @@
<li><a href="https://github.com/pytest-dev/pytest/">pytest @ GitHub</a></li>
<li><a href="http://plugincompat.herokuapp.com/">3rd party plugins</a></li>
<li><a href="https://github.com/pytest-dev/pytest/issues">Issue Tracker</a></li>
<li><a href="http://pytest.org/latest/pytest.pdf">PDF Documentation</a>
<li><a href="https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf">PDF Documentation</a>
</ul>

View File

@@ -1,3 +1,7 @@
:orphan:
.. warnings about this file not being included in any toctree will be suppressed by :orphan:
April 2015 is "adopt pytest month"
=============================================

View File

@@ -5,7 +5,15 @@ Release announcements
.. toctree::
:maxdepth: 2
release-3.0.7
release-3.0.6
release-3.0.5
release-3.0.4
release-3.0.3
release-3.0.2
release-3.0.1
release-3.0.0
sprint2016
release-2.9.2
release-2.9.1

View File

@@ -63,9 +63,9 @@ Changes between 2.0.1 and 2.0.2
this.
- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
thanks to Laura Creighton who also revieved parts of the documentation.
thanks to Laura Creighton who also reviewed parts of the documentation.
- fix slighly wrong output of verbose progress reporting for classes
- fix slightly wrong output of verbose progress reporting for classes
(thanks Amaury)
- more precise (avoiding of) deprecation warnings for node.Class|Function accesses

View File

@@ -13,7 +13,7 @@ If you want to install or upgrade pytest, just type one of::
easy_install -U pytest
There also is a bugfix release 1.6 of pytest-xdist, the plugin
that enables seemless distributed and "looponfail" testing for Python.
that enables seamless distributed and "looponfail" testing for Python.
best,
holger krekel
@@ -33,7 +33,7 @@ Changes between 2.0.2 and 2.0.3
- don't require zlib (and other libs) for genscript plugin without
--genscript actually being used.
- speed up skips (by not doing a full traceback represenation
- speed up skips (by not doing a full traceback representation
internally)
- fix issue37: avoid invalid characters in junitxml's output

View File

@@ -2,7 +2,7 @@ pytest-2.2.1: bug fixes, perfect teardowns
===========================================================================
pytest-2.2.1 is a minor backward-compatible release of the the py.test
pytest-2.2.1 is a minor backward-compatible release of the py.test
testing tool. It contains bug fixes and little improvements, including
documentation fixes. If you are using the distributed testing
pluginmake sure to upgrade it to pytest-xdist-1.8.

View File

@@ -29,7 +29,7 @@ Changes between 2.2.3 and 2.2.4
- fix issue with unittest: now @unittest.expectedFailure markers should
be processed correctly (you can also use @pytest.mark markers)
- document integration with the extended distribute/setuptools test commands
- fix issue 140: propperly get the real functions
- fix issue 140: properly get the real functions
of bound classmethods for setup/teardown_class
- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
- fix issue #143: call unconfigure/sessionfinish always when

View File

@@ -89,7 +89,7 @@ Changes between 2.2.4 and 2.3.0
- fix issue128: show captured output when capsys/capfd are used
- fix issue179: propperly show the dependency chain of factories
- fix issue179: properly show the dependency chain of factories
- pluginmanager.register(...) now raises ValueError if the
plugin has been already registered or the name is taken
@@ -130,5 +130,5 @@ Changes between 2.2.4 and 2.3.0
- don't show deselected reason line if there is none
- py.test -vv will show all of assert comparisations instead of truncating
- py.test -vv will show all of assert comparisons instead of truncating

View File

@@ -1,7 +1,7 @@
pytest-2.3.2: some fixes and more traceback-printing speed
===========================================================================
pytest-2.3.2 is a another stabilization release:
pytest-2.3.2 is another stabilization release:
- issue 205: fixes a regression with conftest detection
- issue 208/29: fixes traceback-printing speed in some bad cases

View File

@@ -1,7 +1,7 @@
pytest-2.3.3: integration fixes, py24 suport, ``*/**`` shown in traceback
pytest-2.3.3: integration fixes, py24 support, ``*/**`` shown in traceback
===========================================================================
pytest-2.3.3 is a another stabilization release of the py.test tool
pytest-2.3.3 is another stabilization release of the py.test tool
which offers uebersimple assertions, scalable fixture mechanisms
and deep customization for testing with Python. Particularly,
this release provides:
@@ -46,7 +46,7 @@ Changes between 2.3.2 and 2.3.3
- fix issue209 - reintroduce python2.4 support by depending on newer
pylib which re-introduced statement-finding for pre-AST interpreters
- nose support: only call setup if its a callable, thanks Andrew
- nose support: only call setup if it's a callable, thanks Andrew
Taumoefolau
- fix issue219 - add py2.4-3.3 classifiers to TROVE list

View File

@@ -44,11 +44,11 @@ Changes between 2.3.4 and 2.3.5
(thanks Adam Goucher)
- Issue 265 - integrate nose setup/teardown with setupstate
so it doesnt try to teardown if it did not setup
so it doesn't try to teardown if it did not setup
- issue 271 - dont write junitxml on slave nodes
- issue 271 - don't write junitxml on slave nodes
- Issue 274 - dont try to show full doctest example
- Issue 274 - don't try to show full doctest example
when doctest does not know the example location
- issue 280 - disable assertion rewriting on buggy CPython 2.6.0
@@ -84,7 +84,7 @@ Changes between 2.3.4 and 2.3.5
- allow to specify prefixes starting with "_" when
customizing python_functions test discovery. (thanks Graham Horler)
- improve PYTEST_DEBUG tracing output by puting
- improve PYTEST_DEBUG tracing output by putting
extra data on a new lines with additional indent
- ensure OutcomeExceptions like skip/fail have initialized exception attributes

View File

@@ -36,7 +36,7 @@ a full list of details. A few feature highlights:
- reporting: color the last line red or green depending if
failures/errors occurred or everything passed.
The documentation has been updated to accomodate the changes,
The documentation has been updated to accommodate the changes,
see `http://pytest.org <http://pytest.org>`_
To install or upgrade pytest::
@@ -118,7 +118,7 @@ new features:
- fix issue322: tearDownClass is not run if setUpClass failed. Thanks
Mathieu Agopian for the initial fix. Also make all of pytest/nose
finalizer mimick the same generic behaviour: if a setupX exists and
finalizer mimic the same generic behaviour: if a setupX exists and
fails, don't run teardownX. This internally introduces a new method
"node.addfinalizer()" helper which can only be called during the setup
phase of a node.

View File

@@ -70,7 +70,7 @@ holger krekel
to problems for more than >966 non-function scoped parameters).
- fix issue290 - there is preliminary support now for parametrizing
with repeated same values (sometimes useful to to test if calling
with repeated same values (sometimes useful to test if calling
a second time works as with the first time).
- close issue240 - document precisely how pytest module importing
@@ -149,7 +149,7 @@ holger krekel
would not work correctly because pytest assumes @pytest.mark.some
gets a function to be decorated already. We now at least detect if this
arg is an lambda and thus the example will work. Thanks Alex Gaynor
arg is a lambda and thus the example will work. Thanks Alex Gaynor
for bringing it up.
- xfail a test on pypy that checks wrong encoding/ascii (pypy does

View File

@@ -60,5 +60,5 @@ holger krekel
- fix issue429: comparing byte strings with non-ascii chars in assert
expressions now work better. Thanks Floris Bruynooghe.
- make capfd/capsys.capture private, its unused and shouldnt be exposed
- make capfd/capsys.capture private, its unused and shouldn't be exposed

View File

@@ -41,8 +41,8 @@ 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.
Thanks to Wolfgang Schnerring for figuring out a reproducable example.
CWD outside of a test package pytest would get fixture discovery wrong.
Thanks to Wolfgang Schnerring for figuring out a reproducible example.
- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
timeout when interactively entering pdb). Thanks Wolfgang Schnerring.

View File

@@ -32,7 +32,7 @@ The py.test Development Team
explanations. Thanks Carl Meyer for the report and test case.
- fix issue553: properly handling inspect.getsourcelines failures in
FixtureLookupError which would lead to to an internal error,
FixtureLookupError which would lead to an internal error,
obfuscating the original problem. Thanks talljosh for initial
diagnose/patch and Bruno Oliveira for final patch.

View File

@@ -63,3 +63,5 @@ The py.test Development Team
.. _#649: https://github.com/pytest-dev/pytest/issues/649
.. _@asottile: https://github.com/asottile
.. _@nicoddemus: https://github.com/nicoddemus
.. _@tomviner: https://github.com/tomviner

View File

@@ -46,7 +46,7 @@ The py.test Development Team
Thanks `@astraw38`_ for reporting the issue (`#1496`_) and `@tomviner`_
for PR the (`#1524`_).
* Fix win32 path issue when puttinging custom config file with absolute path
* Fix win32 path issue when putting custom config file with absolute path
in ``pytest.main("-c your_absolute_path")``.
* Fix maximum recursion depth detection when raised error class is not aware
@@ -69,5 +69,10 @@ The py.test Development Team
.. _#1496: https://github.com/pytest-dev/pytest/issue/1496
.. _#1524: https://github.com/pytest-dev/pytest/issue/1524
.. _@prusse-martin: https://github.com/prusse-martin
.. _@astraw38: https://github.com/astraw38
.. _@hackebrot: https://github.com/hackebrot
.. _@omarkohl: https://github.com/omarkohl
.. _@pquentin: https://github.com/pquentin
.. _@prusse-martin: https://github.com/prusse-martin
.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
.. _@tomviner: https://github.com/tomviner

View File

@@ -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/

View File

@@ -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

View File

@@ -0,0 +1,24 @@
pytest-3.0.2
============
pytest 3.0.2 has just been released to PyPI.
This release fixes some regressions and bugs reported in version 3.0.1, 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:
* Ahn Ki-Wook
* Bruno Oliveira
* Florian Bruhin
* Jordan Guymon
* Raphael Pierzina
* Ronny Pfannschmidt
* mbyt
Happy testing,
The pytest Development Team

View File

@@ -0,0 +1,27 @@
pytest-3.0.3
============
pytest 3.0.3 has just been released to PyPI.
This release fixes some regressions and bugs reported in the last version,
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:
* Bruno Oliveira
* Florian Bruhin
* Floris Bruynooghe
* Huayi Zhang
* Lev Maximov
* Raquel Alegre
* Ronny Pfannschmidt
* Roy Williams
* Tyler Goodlet
* mbyt
Happy testing,
The pytest Development Team

View File

@@ -0,0 +1,29 @@
pytest-3.0.4
============
pytest 3.0.4 has just been released to PyPI.
This release fixes some regressions and bugs reported in the last version,
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:
* Bruno Oliveira
* Dan Wandschneider
* Florian Bruhin
* Georgy Dyuldin
* Grigorii Eremeev
* Jason R. Coombs
* Manuel Jacob
* Mathieu Clabaut
* Michael Seifert
* Nikolaus Rath
* Ronny Pfannschmidt
* Tom V
Happy testing,
The pytest Development Team

View File

@@ -0,0 +1,27 @@
pytest-3.0.5
============
pytest 3.0.5 has just been released to PyPI.
This is a bug-fix release, 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:
* Ana Vojnovic
* Bruno Oliveira
* Daniel Hahler
* Duncan Betts
* Igor Starikov
* Ismail
* Luke Murphy
* Ned Batchelder
* Ronny Pfannschmidt
* Sebastian Ramacher
* nmundar
Happy testing,
The pytest Development Team

View File

@@ -0,0 +1,33 @@
pytest-3.0.6
============
pytest 3.0.6 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
Thanks to all who contributed to this release, among them:
* Andreas Pelme
* Bruno Oliveira
* Dmitry Malinovsky
* Eli Boyarski
* Jakub Wilk
* Jeff Widman
* Loïc Estève
* Luke Murphy
* Miro Hrončok
* Oscar Hellström
* Peter Heatwole
* Philippe Ombredanne
* Ronny Pfannschmidt
* Rutger Prins
* Stefan Scherfke
Happy testing,
The pytest Development Team

View File

@@ -0,0 +1,33 @@
pytest-3.0.7
============
pytest 3.0.7 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
Thanks to all who contributed to this release, among them:
* Anthony Sottile
* Barney Gale
* Bruno Oliveira
* Florian Bruhin
* Floris Bruynooghe
* Ionel Cristian Mărieș
* Katerina Koukiou
* NODA, Kai
* Omer Hadari
* Patrick Hayes
* Ran Benita
* Ronny Pfannschmidt
* Victor Uriarte
* Vidar Tonaas Fauske
* Ville Skyttä
* fbjorn
* mbyt
Happy testing,
The pytest Development Team

View File

@@ -39,8 +39,6 @@ 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
Ronny Pfannschmidt, Germany
Sprint organisation, schedule

View File

@@ -26,8 +26,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 items
test_assert1.py F
@@ -170,8 +170,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 items
test_assert2.py F
@@ -183,7 +183,7 @@ if you run this module::
set1 = set("1308")
set2 = set("8035")
> assert set1 == set2
E assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'}
E AssertionError: assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'}
E Extra items in the left set:
E '1'
E Extra items in the right set:
@@ -208,6 +208,7 @@ It is possible to add your own detailed explanations by implementing
the ``pytest_assertrepr_compare`` hook.
.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
:noindex:
As an example consider adding the following hook in a conftest.py which
provides an alternative explanation for ``Foo`` objects::
@@ -261,50 +262,20 @@ Advanced assertion introspection
.. versionadded:: 2.1
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``.
By default, ``pytest`` rewrites assert statements in test modules.
Rewritten assert statements put introspection information into the assertion failure message.
``pytest`` only rewrites test modules directly discovered by its test collection process, so
asserts in supporting modules which are not themselves test modules will not be
rewritten.
Reporting details about a failing assertion is achieved by rewriting assert
statements before they are run. Rewritten assert statements put introspection
information into the assertion failure message. ``pytest`` only rewrites test
modules directly discovered by its test collection process, so asserts in
supporting modules which are not themselves test modules will not be rewritten.
.. note::
``pytest`` rewrites test modules on import. It does this by using an import
hook to write a new pyc files. Most of the time this works transparently.
hook to write new pyc files. Most of the time this works transparently.
However, if you are messing with import yourself, the import hook may
interfere. If this is the case, simply use ``--assert=reinterp`` or
``--assert=plain``. Additionally, rewriting will fail silently if it cannot
write new pycs, i.e. in a read-only filesystem or a zipfile.
If an assert statement has not been rewritten or the Python version is less than
2.6, ``pytest`` falls back on assert reinterpretation. In assert
reinterpretation, ``pytest`` walks the frame of the function containing the
assert statement to discover sub-expression results of the failing assert
statement. You can force ``pytest`` to always use assertion reinterpretation by
passing the ``--assert=reinterp`` option.
Assert reinterpretation has a caveat not present with assert rewriting: If
evaluating the assert expression has side effects you may get a warning that the
intermediate values could not be determined safely. A common example of this
issue is an assertion which reads from a file::
assert f.read() != '...'
If this assertion fails then the re-evaluation will probably succeed!
This is because ``f.read()`` will return an empty string when it is
called the second time during the re-evaluation. However, it is
easy to rewrite the assertion and avoid any trouble::
content = f.read()
assert content != '...'
All assert introspection can be turned off by passing ``--assert=plain``.
interfere. If this is the case, use ``--assert=plain``. Additionally,
rewriting will fail silently if it cannot write new pycs, i.e. in a read-only
filesystem or a zipfile.
For further information, Benjamin Peterson wrote up `Behind the scenes of pytest's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_.
@@ -316,4 +287,5 @@ For further information, Benjamin Peterson wrote up `Behind the scenes of pytest
``--nomagic``.
.. versionchanged:: 3.0
Removes the ``--no-assert`` and``--nomagic`` options.
Removes the ``--no-assert`` and ``--nomagic`` options.
Removes the ``--assert=reinterp`` option.

View File

@@ -58,13 +58,13 @@ Fixtures and requests
To mark a fixture function:
.. autofunction:: _pytest.python.fixture
.. autofunction:: _pytest.fixtures.fixture
Tutorial at :ref:`fixtures`.
The ``request`` object that can be used from fixture functions.
.. autoclass:: _pytest.python.FixtureRequest()
.. autoclass:: _pytest.fixtures.FixtureRequest()
:members:

View File

@@ -80,9 +80,9 @@ 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.7, py-1.4.32, pluggy-0.4.0
run-last-failure: rerun last 2 failures
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collected 50 items
test_50.py FF
@@ -122,9 +122,9 @@ 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.7, py-1.4.32, pluggy-0.4.0
run-last-failure: rerun last 2 failures first
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collected 50 items
test_50.py FF................................................
@@ -227,8 +227,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
cachedir: $REGENDOC_TMPDIR/.cache
------------------------------- cache values -------------------------------
cache/lastfailed contains:
@@ -246,7 +246,7 @@ by adding the ``--cache-clear`` option like this::
pytest --cache-clear
This is recommended for invocations from Continous Integration
This is recommended for invocations from Continuous Integration
servers where isolation and correctness is more important
than speed.

View File

@@ -64,8 +64,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 2 items
test_module.py .F

View File

@@ -19,11 +19,8 @@
# The short X.Y version.
import os, sys
sys.path.insert(0, os.path.dirname(__file__))
import _getdoctarget
version = _getdoctarget.get_minor_version_string()
release = _getdoctarget.get_version_string()
from _pytest import __version__ as version
release = ".".join(version.split(".")[:2])
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -127,7 +124,7 @@ html_theme_options = {
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = None
html_title = 'pytest documentation'
# A shorter title for the navigation bar. Default is the same as html_title.
html_short_title = "pytest-%s" % release
@@ -144,7 +141,7 @@ html_favicon = "img/pytest1favi.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
@@ -306,7 +303,7 @@ texinfo_documents = [
('Holger Krekel@*Benjamin Peterson@*Ronny Pfannschmidt@*'
'Floris Bruynooghe@*others'),
'pytest',
'simple powerful testing with Pytho',
'simple powerful testing with Python',
'Programming',
1),
]

View File

@@ -10,32 +10,51 @@ Full pytest documentation
.. toctree::
:maxdepth: 2
overview
apiref
example/index
getting-started
usage
assert
builtin
fixture
monkeypatch
tmpdir
capture
recwarn
doctest
mark
skipping
parametrize
cache
plugins
unittest
nose
xunit_setup
plugins
writing_plugins
example/index
goodpractices
customize
bash-completion
backwards-compatibility
license
contributing
talks
projects
faq
contact
.. only:: html
.. toctree::
:maxdepth: 1
funcarg_compare
announce/index
.. only:: html
.. toctree::
:hidden:
:maxdepth: 1
changelog

View File

@@ -48,6 +48,16 @@ Here is the algorithm which finds the rootdir from ``args``:
directory. This allows to work with pytest in structures that are not part of
a package and don't have any particular ini-file configuration.
If no ``args`` are given, pytest collects test below the current working
directory and also starts determining the rootdir from there.
:warning: custom pytest plugin commandline arguments may include a path, as in
``pytest --log-output ../../test.log args``. Then ``args`` is mandatory,
otherwise pytest uses the folder of test.log for rootdir determination
(see also `issue 1435 <https://github.com/pytest-dev/pytest/issues/1435>`_).
A dot ``.`` for referencing to the current working directory is also
possible.
Note that an existing ``pytest.ini`` file will always be considered a match,
whereas ``tox.ini`` and ``setup.cfg`` will only match if they contain a
``[pytest]`` or ``[tool:pytest]`` section, respectively. Options from multiple ini-files candidates are never

View File

@@ -16,6 +16,7 @@ from docstrings in all python modules (including regular
python test modules)::
pytest --doctest-modules
You can make these changes permanent in your project by
putting them into a pytest.ini file like this:
@@ -48,7 +49,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.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
collected 1 items

View File

@@ -1,4 +0,0 @@
[pytest]
testfilepatterns =
${topdir}/tests/unit/test_${basename}
${topdir}/tests/functional/*.py

View File

@@ -31,9 +31,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 4 items
test_server.py::test_send_http PASSED
@@ -45,9 +45,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 4 items
test_server.py::test_something_quick PASSED
@@ -66,9 +66,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 5 items
test_server.py::TestClass::test_method PASSED
@@ -79,9 +79,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 4 items
test_server.py::TestClass::test_method PASSED
@@ -92,9 +92,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 8 items
test_server.py::TestClass::test_method PASSED
@@ -130,9 +130,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 4 items
test_server.py::test_send_http PASSED
@@ -144,9 +144,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 4 items
test_server.py::test_something_quick PASSED
@@ -160,9 +160,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 4 items
test_server.py::test_send_http PASSED
@@ -205,7 +205,7 @@ You can ask which markers exist for your test suite - the list includes our just
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
@@ -352,8 +352,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 items
test_someenv.py s
@@ -364,8 +364,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 items
test_someenv.py .
@@ -381,7 +381,7 @@ The ``--markers`` option always gives you a list of available markers::
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
@@ -450,7 +450,7 @@ for your particular platform, you could use the following plugin::
import sys
import pytest
ALL = set("darwin linux2 win32".split())
ALL = set("darwin linux win32".split())
def pytest_runtest_setup(item):
if isinstance(item, item.Function):
@@ -470,7 +470,7 @@ Let's do a little test file to show how this looks like::
def test_if_apple_is_evil():
pass
@pytest.mark.linux2
@pytest.mark.linux
def test_if_linux_works():
pass
@@ -481,32 +481,32 @@ Let's do a little test file to show how this looks like::
def test_runs_everywhere():
pass
then you will see two test skipped and two executed tests as expected::
then you will see two tests 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 4 items
test_plat.py sss.
test_plat.py s.s.
======= short test summary info ========
SKIP [3] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux
SKIP [2] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux
======= 1 passed, 3 skipped in 0.12 seconds ========
======= 2 passed, 2 skipped in 0.12 seconds ========
Note that if you specify a platform via the marker-command line option like this::
$ pytest -m linux2
$ pytest -m linux
======= test session starts ========
platform linux -- Python 3.5.2, pytest-3.0.0, py-1.4.31, pluggy-0.3.1
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 4 items
test_plat.py s
test_plat.py .
======= 3 tests deselected ========
======= 1 skipped, 3 deselected in 0.12 seconds ========
======= 1 passed, 3 deselected in 0.12 seconds ========
then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests.
@@ -551,8 +551,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 4 items
test_module.py FF
@@ -573,8 +573,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 4 items
test_module.py FFF

View File

@@ -27,8 +27,8 @@ 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
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
collected 2 items
test_simple.yml F.
@@ -59,9 +59,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
collecting ... collected 2 items
test_simple.yml::hello FAILED
@@ -81,8 +81,8 @@ 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
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
collected 2 items
<YamlFile 'test_simple.yml'>
<YamlItem 'hello'>

View File

@@ -130,8 +130,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 6 items
<Module 'test_time.py'>
<Function 'test_timedistance_v0[a0-b0-expected0]'>
@@ -181,8 +181,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 4 items
test_scenarios.py ....
@@ -194,8 +194,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 4 items
<Module 'test_scenarios.py'>
<Class 'TestSampleWithScenarios'>
@@ -259,8 +259,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 2 items
<Module 'test_backends.py'>
<Function 'test_db_initialized[d1]'>
@@ -320,8 +320,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 items
<Module 'test_indirect_list.py'>
<Function 'test_indirect[a-b]'>
@@ -447,8 +447,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 2 items
test_module.py .s

View File

@@ -95,7 +95,7 @@ the :confval:`python_files`, :confval:`python_classes` and
:confval:`python_functions` configuration options. Example::
# content of pytest.ini
# can also be defined in in tox.ini or setup.cfg file, although the section
# can also be defined in tox.ini or setup.cfg file, although the section
# name in setup.cfg files should be "tool:pytest"
[pytest]
python_files=check_*.py
@@ -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.7, py-1.4.32, pluggy-0.4.0
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.7, py-1.4.32, pluggy-0.4.0
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.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
collected 0 items

View File

@@ -7,14 +7,12 @@ Demo of Python failure reports with pytest
Here is a nice run of several tens of failures
and how ``pytest`` presents things (unfortunately
not showing the nice colors here in the HTML that you
get on the terminal - we are working on that):
.. code-block:: python
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
rootdir: $REGENDOC_TMPDIR/assertion, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR/assertion, inifile:
collected 42 items
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
@@ -83,7 +81,7 @@ get on the terminal - we are working on that):
def test_eq_text(self):
> assert 'spam' == 'eggs'
E assert 'spam' == 'eggs'
E AssertionError: assert 'spam' == 'eggs'
E - spam
E + eggs
@@ -94,7 +92,7 @@ get on the terminal - we are working on that):
def test_eq_similar_text(self):
> assert 'foo 1 bar' == 'foo 2 bar'
E assert 'foo 1 bar' == 'foo 2 bar'
E AssertionError: assert 'foo 1 bar' == 'foo 2 bar'
E - foo 1 bar
E ? ^
E + foo 2 bar
@@ -107,7 +105,7 @@ get on the terminal - we are working on that):
def test_eq_multiline_text(self):
> assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
E assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
E AssertionError: assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
E foo
E - spam
E + eggs
@@ -122,7 +120,7 @@ get on the terminal - we are working on that):
a = '1'*100 + 'a' + '2'*100
b = '1'*100 + 'b' + '2'*100
> assert a == b
E assert '111111111111...2222222222222' == '1111111111111...2222222222222'
E AssertionError: assert '111111111111...2222222222222' == '1111111111111...2222222222222'
E Skipping 90 identical leading characters in diff, use -v to show
E Skipping 91 identical trailing characters in diff, use -v to show
E - 1111111111a222222222
@@ -139,7 +137,7 @@ get on the terminal - we are working on that):
a = '1\n'*100 + 'a' + '2\n'*100
b = '1\n'*100 + 'b' + '2\n'*100
> assert a == b
E assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n1...n2\n2\n2\n2\n'
E AssertionError: assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n1...n2\n2\n2\n2\n'
E Skipping 190 identical leading characters in diff, use -v to show
E Skipping 191 identical trailing characters in diff, use -v to show
E 1
@@ -185,7 +183,7 @@ get on the terminal - we are working on that):
def test_eq_dict(self):
> assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
E assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
E AssertionError: assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
E Omitting 1 identical items, use -v to show
E Differing items:
E {'b': 1} != {'b': 2}
@@ -240,7 +238,7 @@ get on the terminal - we are working on that):
def test_not_in_text_multiline(self):
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
> assert 'foo' not in text
E assert 'foo' not in 'some multiline\ntext\nw...ncludes foo\nand a\ntail'
E AssertionError: assert 'foo' not in 'some multiline\ntext\nw...ncludes foo\nand a\ntail'
E 'foo' is contained here:
E some multiline
E text
@@ -258,7 +256,7 @@ get on the terminal - we are working on that):
def test_not_in_text_single(self):
text = 'single foo line'
> assert 'foo' not in text
E assert 'foo' not in 'single foo line'
E AssertionError: assert 'foo' not in 'single foo line'
E 'foo' is contained here:
E single foo line
E ? +++
@@ -271,7 +269,7 @@ get on the terminal - we are working on that):
def test_not_in_text_single_long(self):
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
> assert 'foo' not in text
E assert 'foo' not in 'head head head head hea...ail tail tail tail tail '
E AssertionError: assert 'foo' not in 'head head head head hea...ail tail tail tail tail '
E 'foo' is contained here:
E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
E ? +++
@@ -284,7 +282,7 @@ get on the terminal - we are working on that):
def test_not_in_text_single_long_term(self):
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
> assert 'f'*70 not in text
E assert 'fffffffffff...ffffffffffff' not in 'head head he...l tail tail '
E AssertionError: assert 'fffffffffff...ffffffffffff' not in 'head head he...l tail tail '
E 'ffffffffffffffffff...fffffffffffffffffff' is contained here:
E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -307,7 +305,7 @@ get on the terminal - we are working on that):
class Foo(object):
b = 1
> assert Foo().b == 2
E assert 1 == 2
E AssertionError: assert 1 == 2
E + where 1 = <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef>.b
E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
@@ -340,7 +338,7 @@ get on the terminal - we are working on that):
class Bar(object):
b = 2
> assert Foo().b == Bar().b
E assert 1 == 2
E AssertionError: assert 1 == 2
E + where 1 = <failure_demo.test_attribute_multiple.<locals>.Foo object at 0xdeadbeef>.b
E + where <failure_demo.test_attribute_multiple.<locals>.Foo object at 0xdeadbeef> = <class 'failure_demo.test_attribute_multiple.<locals>.Foo'>()
E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0xdeadbeef>.b
@@ -361,7 +359,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:1207>:1: ValueError
_______ TestRaises.test_raises_doesnt ________
self = <failure_demo.TestRaises object at 0xdeadbeef>
@@ -482,7 +480,7 @@ get on the terminal - we are working on that):
s = "123"
g = "456"
> assert s.startswith(g)
E assert False
E AssertionError: assert False
E + where False = <built-in method startswith of str object at 0xdeadbeef>('456')
E + where <built-in method startswith of str object at 0xdeadbeef> = '123'.startswith
@@ -497,7 +495,7 @@ get on the terminal - we are working on that):
def g():
return "456"
> assert f().startswith(g())
E assert False
E AssertionError: assert False
E + where False = <built-in method startswith of str object at 0xdeadbeef>('456')
E + where <built-in method startswith of str object at 0xdeadbeef> = '123'.startswith
E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0xdeadbeef>()

View File

@@ -1,5 +1,4 @@
.. highlightlang:: python
Basic patterns and examples
==========================================================
@@ -10,7 +9,9 @@ Pass different values to a test function, depending on command line options
.. regendoc:wipe
Suppose we want to write a test that depends on a command line option.
Here is a basic pattern to achieve this::
Here is a basic pattern to achieve this:
.. code-block:: python
# content of test_sample.py
def test_answer(cmdopt):
@@ -22,7 +23,9 @@ Here is a basic pattern to achieve this::
For this to work we need to add a command line option and
provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`::
provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`:
.. code-block:: python
# content of conftest.py
import pytest
@@ -91,7 +94,9 @@ Dynamically adding command line options
Through :confval:`addopts` you can statically add command line
options for your project. You can also dynamically modify
the command line arguments before they get processed::
the command line arguments before they get processed:
.. code-block:: python
# content of conftest.py
import sys
@@ -101,15 +106,15 @@ the command line arguments before they get processed::
num = max(multiprocessing.cpu_count() / 2, 1)
args[:] = ["-n", str(num)] + args
If you have the :ref:`xdist plugin <xdist>` installed
If you have the `xdist plugin <https://pypi.python.org/pypi/pytest-xdist>`_ installed
you will now always perform test runs using a number
of subprocesses close to your CPU. Running in an empty
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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 0 items
======= no tests ran in 0.12 seconds ========
@@ -122,7 +127,9 @@ Control skipping of tests according to command line option
.. regendoc:wipe
Here is a ``conftest.py`` file adding a ``--runslow`` command
line option to control skipping of ``slow`` marked tests::
line option to control skipping of ``slow`` marked tests:
.. code-block:: python
# content of conftest.py
@@ -131,10 +138,11 @@ line option to control skipping of ``slow`` marked tests::
parser.addoption("--runslow", action="store_true",
help="run slow tests")
We can now write a test module like this::
We can now write a test module like this:
.. code-block:: python
# content of test_module.py
import pytest
@@ -156,13 +164,13 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 2 items
test_module.py .s
======= short test summary info ========
SKIP [1] test_module.py:14: need --runslow option to run
SKIP [1] test_module.py:13: need --runslow option to run
======= 1 passed, 1 skipped in 0.12 seconds ========
@@ -170,8 +178,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 2 items
test_module.py ..
@@ -187,7 +195,9 @@ If you have a test helper function called from a test you can
use the ``pytest.fail`` marker to fail a test with a certain message.
The test support function will not show up in the traceback if you
set the ``__tracebackhide__`` option somewhere in the helper function.
Example::
Example:
.. code-block:: python
# content of test_checkconfig.py
import pytest
@@ -218,7 +228,9 @@ Let's run our little function::
If you only want to hide certain exceptions, you can set ``__tracebackhide__``
to a callable which gets the ``ExceptionInfo`` object. You can for example use
this to make sure unexpected exception types aren't hidden::
this to make sure unexpected exception types aren't hidden:
.. code-block:: python
import operator
import pytest
@@ -246,7 +258,9 @@ Detect if running from within a pytest run
Usually it is a bad idea to make application code
behave differently if called from a test. But if you
absolutely must find out if your application code is
running from a test you can do something like this::
running from a test you can do something like this:
.. code-block:: python
# content of conftest.py
@@ -257,7 +271,9 @@ running from a test you can do something like this::
def pytest_unconfigure(config):
del sys._called_from_test
and then check for the ``sys._called_from_test`` flag::
and then check for the ``sys._called_from_test`` flag:
.. code-block:: python
if hasattr(sys, '_called_from_test'):
# called from within a test run
@@ -273,7 +289,9 @@ Adding info to test report header
.. regendoc:wipe
It's easy to present extra information in a ``pytest`` run::
It's easy to present extra information in a ``pytest`` run:
.. code-block:: python
# content of conftest.py
@@ -284,19 +302,20 @@ 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.7, py-1.4.32, pluggy-0.4.0
project deps: mylib-1.1
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collected 0 items
======= no tests ran in 0.12 seconds ========
.. regendoc:wipe
You can also return a list of strings which will be considered as several
lines of information. You can of course also make the amount of reporting
information on e.g. the value of ``config.getoption('verbose')`` so that
you present more information appropriately::
It is also possible to return a list of strings which will be considered as several
lines of information. You may consider ``config.getoption('verbose')`` in order to
display more information if applicable:
.. code-block:: python
# content of conftest.py
@@ -308,11 +327,11 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
info1: did you know that ...
did you?
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 0 items
======= no tests ran in 0.12 seconds ========
@@ -321,8 +340,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 0 items
======= no tests ran in 0.12 seconds ========
@@ -335,10 +354,11 @@ profiling test duration
.. versionadded: 2.2
If you have a slow running large test suite you might want to find
out which tests are the slowest. Let's make an artificial test suite::
out which tests are the slowest. Let's make an artificial test suite:
.. code-block:: python
# content of test_some_are_slow.py
import time
def test_funcfast():
@@ -354,8 +374,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 3 items
test_some_are_slow.py ...
@@ -375,7 +395,9 @@ Sometimes you may have a testing situation which consists of a series
of test steps. If one step fails it makes no sense to execute further
steps as they are all expected to fail anyway and their tracebacks
add no insight. Here is a simple ``conftest.py`` file which introduces
an ``incremental`` marker which is to be used on classes::
an ``incremental`` marker which is to be used on classes:
.. code-block:: python
# content of conftest.py
@@ -394,7 +416,9 @@ an ``incremental`` marker which is to be used on classes::
pytest.xfail("previous test failed (%s)" %previousfailed.name)
These two hook implementations work together to abort incremental-marked
tests in a class. Here is a test module example::
tests in a class. Here is a test module example:
.. code-block:: python
# content of test_step.py
@@ -416,8 +440,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 4 items
test_step.py .Fx.
@@ -452,7 +476,9 @@ concept. It's however recommended to have explicit fixture references in your
tests or test classes rather than relying on implicitly executing
setup/teardown functions, especially if they are far away from the actual tests.
Here is a an example for making a ``db`` fixture available in a directory::
Here is an example for making a ``db`` fixture available in a directory:
.. code-block:: python
# content of a/conftest.py
import pytest
@@ -464,20 +490,26 @@ Here is a an example for making a ``db`` fixture available in a directory::
def db():
return DB()
and then a test module in that directory::
and then a test module in that directory:
.. code-block:: python
# content of a/test_db.py
def test_a1(db):
assert 0, db # to show value
another test module::
another test module:
.. code-block:: python
# content of a/test_db2.py
def test_a2(db):
assert 0, db # to show value
and then a module in a sister directory which will not see
the ``db`` fixture::
the ``db`` fixture:
.. code-block:: python
# content of b/test_error.py
def test_root(db): # no db here, will error out
@@ -487,8 +519,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 7 items
test_step.py .Fx.
@@ -553,7 +585,9 @@ environment you can implement a hook that gets called when the test
"report" object is about to be created. Here we write out all failing
test calls and also access a fixture (if it was used by the test) in
case you want to query/look at it during your post processing. In our
case we just write some informations out to a ``failures`` file::
case we just write some information out to a ``failures`` file:
.. code-block:: python
# content of conftest.py
@@ -579,7 +613,9 @@ case we just write some informations out to a ``failures`` file::
f.write(rep.nodeid + extra + "\n")
if you then have failing tests::
if you then have failing tests:
.. code-block:: python
# content of test_module.py
def test_fail1(tmpdir):
@@ -591,8 +627,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 2 items
test_module.py FF
@@ -628,7 +664,9 @@ Making test result information available in fixtures
.. regendoc:wipe
If you want to make test result reports available in fixture finalizers
here is a little example implemented via a local plugin::
here is a little example implemented via a local plugin:
.. code-block:: python
# content of conftest.py
@@ -640,7 +678,7 @@ here is a little example implemented via a local plugin::
outcome = yield
rep = outcome.get_result()
# set an report attribute for each phase of a call, which can
# set a report attribute for each phase of a call, which can
# be "setup", "call", "teardown"
setattr(item, "rep_" + rep.when, rep)
@@ -658,7 +696,9 @@ here is a little example implemented via a local plugin::
print ("executing test failed", request.node.nodeid)
if you then have failing tests::
if you then have failing tests:
.. code-block:: python
# content of test_module.py
@@ -681,8 +721,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 3 items
test_module.py Esetting up a test failed! test_module.py::test_setup_fails

View File

@@ -66,14 +66,6 @@ This completely avoids previous issues of confusing assertion-reporting.
It also means, that you can use Python's ``-O`` optimization without losing
assertions in test modules.
``pytest`` contains a second, mostly obsolete, assert debugging technique
invoked via ``--assert=reinterpret``: When an ``assert`` statement fails, ``pytest`` re-interprets
the expression part to show intermediate values. This technique suffers
from a caveat that the rewriting does not: If your expression has side
effects (better to avoid them anyway!) the intermediate values may not
be the same, confusing the reinterpreter and obfuscating the initial
error (this is also explained at the command line if it happens).
You can also turn off all assertion interaction using the
``--assert=plain`` option.

View File

@@ -1,8 +0,0 @@
What users say:
`py.test is pretty much the best thing ever`_ (Alex Gaynor)
.. _`py.test is pretty much the best thing ever`_ (Alex Gaynor)
http://twitter.com/#!/alex_gaynor/status/22389410366

View File

@@ -11,7 +11,7 @@ pytest fixtures: explicit, modular, scalable
.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit
.. _`purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software
.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection#Definition
.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection
The `purpose of test fixtures`_ is to provide a fixed baseline
upon which tests can reliably and repeatedly execute. pytest fixtures
@@ -70,8 +70,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 items
test_smtpsimple.py F
@@ -188,8 +188,8 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 2 items
test_module.py FF
@@ -243,7 +243,9 @@ Fixture finalization / executing teardown code
pytest supports execution of fixture specific finalization code
when the fixture goes out of scope. By using a ``yield`` statement instead of ``return``, all
the code after the *yield* statement serves as the teardown code.::
the code after the *yield* statement serves as the teardown code:
.. code-block:: python
# content of conftest.py
@@ -257,8 +259,9 @@ the code after the *yield* statement serves as the teardown code.::
print("teardown smtp")
smtp.close()
The ``print`` and ``smtp.close()`` statements will execute when the last test using
the fixture in the module has finished execution, regardless of the exception status of the tests.
The ``print`` and ``smtp.close()`` statements will execute when the last test in
the module has finished execution, regardless of the exception status of the
tests.
Let's execute it::
@@ -274,22 +277,23 @@ occur around each single test. In either case the test
module itself does not need to change or know about these details
of fixture setup.
Note that we can also seamlessly use the ``yield`` syntax with ``with`` statements::
Note that we can also seamlessly use the ``yield`` syntax with ``with`` statements:
.. code-block:: python
# content of test_yield2.py
import smtplib
import pytest
@pytest.fixture
def passwd():
with open("/etc/passwd") as f:
yield f.readlines()
@pytest.fixture(scope="module")
def smtp(request):
with smtplib.SMTP("smtp.gmail.com") as smtp:
yield smtp # provide the fixture value
def test_has_lines(passwd):
assert len(passwd) >= 1
The file ``f`` will be closed after the test finished execution
because the Python ``file`` object supports finalization when
The ``smtp`` connection will be closed after the test finished execution
because the ``smtp`` object automatically closes when
the ``with`` statement ends.
@@ -318,8 +322,7 @@ the ``with`` statement ends.
request.addfinalizer(fin)
return smtp # provide the fixture value
The ``fin`` function will execute when the last test using
the fixture in the module has finished execution.
The ``fin`` function will execute when the last test in the module has finished execution.
This method is still fully supported, but ``yield`` is recommended from 2.10 onward because
it is considered simpler and better describes the natural code flow.
@@ -352,8 +355,8 @@ again, nothing much has changed::
$ pytest -s -q --tb=no
FFfinalizing <smtplib.SMTP object at 0xdeadbeef> (smtp.gmail.com)
.
2 failed, 1 passed in 0.12 seconds
2 failed in 0.12 seconds
Let's quickly create another test module that actually sets the
server URL in its module namespace::
@@ -375,6 +378,8 @@ Running it::
assert 0, smtp.helo()
E AssertionError: (250, b'mail.python.org')
E assert 0
------------------------- Captured stdout teardown -------------------------
finalizing <smtplib.SMTP object at 0xdeadbeef> (mail.python.org)
voila! The ``smtp`` fixture function picked up our mail server name
from the module namespace.
@@ -448,7 +453,7 @@ So let's just do another run::
response, msg = smtp.ehlo()
assert response == 250
> assert b"smtp.gmail.com" in msg
E assert b'smtp.gmail.com' in b'mail.python.org\nSIZE 51200000\nETRN\nSTARTTLS\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8'
E AssertionError: assert b'smtp.gmail.com' in b'mail.python.org\nSIZE 51200000\nETRN\nSTARTTLS\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8'
test_module.py:5: AssertionError
-------------------------- Captured stdout setup ---------------------------
@@ -464,6 +469,8 @@ So let's just do another run::
E assert 0
test_module.py:11: AssertionError
------------------------- Captured stdout teardown -------------------------
finalizing <smtplib.SMTP object at 0xdeadbeef>
4 failed in 0.12 seconds
We see that our two test functions each ran twice, against the different
@@ -516,9 +523,9 @@ 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
rootdir: $REGENDOC_TMPDIR, inifile:
collected 11 items
platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.32, pluggy-0.4.0
rootdir: $REGENDOC_TMPDIR, inifile:
collected 10 items
<Module 'test_anothersmtp.py'>
<Function 'test_showhelo[smtp.gmail.com]'>
<Function 'test_showhelo[mail.python.org]'>
@@ -532,8 +539,6 @@ Running the above tests results in the following test IDs being used::
<Function 'test_noop[smtp.gmail.com]'>
<Function 'test_ehlo[mail.python.org]'>
<Function 'test_noop[mail.python.org]'>
<Module 'test_yield2.py'>
<Function 'test_has_lines'>
======= no tests ran in 0.12 seconds ========
@@ -569,9 +574,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 2 items
test_appsetup.py::test_smtp_exists[smtp.gmail.com] PASSED
@@ -638,9 +643,9 @@ 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.7, py-1.4.32, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5
cachedir: .cache
rootdir: $REGENDOC_TMPDIR, inifile:
rootdir: $REGENDOC_TMPDIR, inifile:
collecting ... collected 8 items
test_module.py::test_0[1] SETUP otherarg 1
@@ -701,7 +706,7 @@ Using fixtures from classes, modules or projects
Sometimes test functions do not directly need access to a fixture object.
For example, tests may require to operate with an empty directory as the
current working directory but otherwise do not care for the concrete
directory. Here is how you can can use the standard `tempfile
directory. Here is how you can use the standard `tempfile
<http://docs.python.org/library/tempfile.html>`_ and pytest fixtures to
achieve it. We separate the creation of the fixture into a conftest.py
file::
@@ -998,7 +1003,7 @@ Given the tests file structure is:
@pytest.mark.parametrize('username', ['directly-overridden-username-other'])
def test_username_other(other_username):
assert username == 'other-directly-overridden-username-other'
assert other_username == 'other-directly-overridden-username-other'
In the example above, a fixture value is overridden by the test parameter value. Note that the value of the fixture
can be overridden this way even if the test doesn't use it directly (doesn't mention it in the function prototype).

Some files were not shown because too many files have changed in this diff Show More