Compare commits

...

1259 Commits
2.9.2 ... 3.1.2

Author SHA1 Message Date
Bruno Oliveira
7cbf265bb5 Preparing release version 3.1.2 2017-06-08 17:37:42 -04:00
Ronny Pfannschmidt
917b9a8352 Merge pull request #2476 from nicoddemus/fix-2459-numpy-comparison
Fix internal error when a recursion error occurs and frames contain objects that can't be compared
2017-06-07 20:34:36 +02:00
Bruno Oliveira
2127a2378a Fix internal error with recursive tracebacks with that frames contain objects that can't be compared
Fix #2459
2017-06-07 14:40:13 -03:00
Ronny Pfannschmidt
d2db6626cf Merge pull request #2466 from nicoddemus/remove-unicode-warning
Remove UnicodeWarning from pytest warnings
2017-06-07 08:00:36 +02:00
Bruno Oliveira
57e2ced969 Merge pull request #2473 from ApaDoctor/docs-fixes
docs: Create links for objects to show the api
2017-06-06 09:52:54 -03:00
Bruno Oliveira
80944e32ad Add CHANGELOG entry 2017-06-06 09:09:54 -03:00
ApaDoctor
54a90e9555 docs: Create links for objects to show the api 2017-06-06 01:10:32 +02:00
Bruno Oliveira
9d41eaedbf Issue UnicodeWarning only for non-ascii unicode
Fix #2463
2017-06-05 10:43:15 -03:00
Bruno Oliveira
5ee9793c99 Fix CHANGELOG issue id
Fix #2467
2017-06-03 17:34:05 -03:00
Bruno Oliveira
1863b7c7b2 Merge pull request #2462 from segevfiner/py36-windowsconsoleio-workaround
[WIP] A workaround for Python 3.6 WindowsConsoleIO breaking with FDCapture
2017-06-03 15:11:36 -03:00
Segev Finer
01ed6dfc3b Added a changelog entry for the WindowsConsoleIO workaround 2017-06-02 12:38:31 +03:00
Segev Finer
59b3693988 Fixed wrong if in the WindowsConsoleIO workaround 2017-06-02 12:34:26 +03:00
Segev Finer
05796be21a A workaround for Python 3.6 WindowsConsoleIO breaking with FDCapture
Python 3.6 implemented unicode console handling for Windows. This works
by reading/writing to the raw console handle using
``{Read,Write}ConsoleW``.

The problem is that we are going to ``dup2`` over the stdio file
descriptors when doing ``FDCapture`` and this will ``CloseHandle`` the
handles used by Python to write to the console. Though there is still some
weirdness and the console handle seems to only be closed randomly and not
on the first call to ``CloseHandle``, or maybe it gets reopened with the
same handle value when we suspend capturing.

The workaround in this case will reopen stdio with a different fd which
also means a different handle by replicating the logic in
"Py_lifecycle.c:initstdio/create_stdio".

See https://github.com/pytest-dev/py/issues/103
2017-06-02 11:19:03 +03:00
Ronny Pfannschmidt
f826b23f58 Merge pull request #2458 from segevfiner/fix-required-options-help
Fix --help with required options
2017-06-02 08:39:19 +02:00
Segev Finer
9abff7f72f Add a docstring to HelpAction 2017-06-01 22:25:09 +03:00
Segev Finer
f74f14f038 Fix --help with required options
This works by adding an argparse Action that will raise an exception in
order to skip the rest of the argument parsing. This prevents argparse
from quitting due to missing required arguments, similar to the way that
the builtin argparse --help option is implemented by raising SystemExit.

Fixes: #1999
2017-06-01 21:29:50 +03:00
Bruno Oliveira
bcbad5b1af Merge pull request #2140 from pelme/issue2121
Handle python_files correctly in assertion rewrite
2017-06-01 07:55:42 -03:00
Ronny Pfannschmidt
5d785e415e Merge pull request #2454 from nicoddemus/xfail-docs
Make it clear that pytest.xfail stops the test
2017-06-01 08:46:49 +02:00
Bruno Oliveira
409d2f1d54 Make it clear that pytest.xfail stops the test
Also did a general review of the document to improve the flow

Fix #810
2017-05-31 19:54:01 -03:00
Bruno Oliveira
cca4de20cf Merge pull request #2450 from nicoddemus/release-3.1.1
Release 3.1.1
2017-05-31 08:55:40 -03:00
Andreas Pelme
c98ad2a0a0 Install py 1.4.33 that contains the fnmatch py.std import fix. 2017-05-31 08:32:51 +02:00
Andreas Pelme
5de203195c Add changelog for #2121 2017-05-31 08:29:19 +02:00
Andreas Pelme
021e843427 Fixed #2121 Use py.paths fnmatch. This fixes an issue where
python_files handled properly when rewriting assertions.
2017-05-31 08:25:04 +02:00
Andreas Pelme
ac9c8fcdab Failing test for issue #2121 2017-05-31 08:25:04 +02:00
Florian Bruhin
3871810d1c Merge pull request #2451 from nicoddemus/update-release-howto
Update HOWTORELEASE
2017-05-31 07:45:33 +02:00
Bruno Oliveira
281fcd5a58 Update HOWTORELEASE
* Remove the CHANGELOG step now that it is automated;
* Overall clean-up and formatting, trying to make the steps more
  explicit;
2017-05-30 22:16:54 -03:00
Bruno Oliveira
2fd7626046 Preparing release version 3.1.1 2017-05-30 17:19:34 -04:00
Bruno Oliveira
0540d72c87 Add extra space between changelog items 2017-05-30 17:15:31 -04:00
Bruno Oliveira
1dee443c2b Merge pull request #2445 from nicoddemus/warnings-remove-filter
No longer override existing warning filters during warnings capture
2017-05-30 18:14:01 -03:00
Bruno Oliveira
32e2642233 No longer override existing warning filters during warnings capture
Fix #2430
2017-05-30 17:17:36 -03:00
Ronny Pfannschmidt
454426cba5 Merge pull request #2446 from nicoddemus/issue-2441
pytest.deprecated_call now captures PendingDeprecationWarning in context manager form
2017-05-30 20:09:37 +02:00
Bruno Oliveira
f96a1d89c5 pytest.deprecated_call now captures PendingDeprecationWarning in context manager form
Fix #2441
2017-05-30 12:52:18 -03:00
Bruno Oliveira
ee0844dbd8 Merge pull request #2431 from RonnyPfannschmidt/towncrier
initial addition of towncrier
2017-05-30 12:41:37 -03:00
Ronny Pfannschmidt
b74c626026 switch changelog management to towncrier 2017-05-30 15:54:15 +02:00
Floris Bruynooghe
6117930642 Merge pull request #2438 from nicoddemus/issue-2434
Fix unicode issue while running doctests in Python 2
2017-05-29 13:36:07 +02:00
Floris Bruynooghe
7bb06b6dad Merge pull request #2439 from nicoddemus/warnings-docs
Warn that warning-capture can break existing suites in the docs and CHANGELOG
2017-05-29 13:34:39 +02:00
Bruno Oliveira
7950c26a8e Add Hui Wang to AUTHORS list 2017-05-26 08:09:29 -03:00
Bruno Oliveira
836dc451f4 Fix unicode issue while running doctests in Python 2
Fix #2434
2017-05-26 07:35:14 -03:00
Bruno Oliveira
8df3e55a31 Merge pull request #2437 from coldnight/master
Correct warnings that contains Unicode message
2017-05-26 07:24:27 -03:00
wanghui
53add4435f Add ChangeLog 2017-05-26 13:14:42 +08:00
wanghui
d7a5c5716f Add UnicodeWarning for unicode warnings in Python2 2017-05-26 13:12:02 +08:00
Bruno Oliveira
313a884459 Warn that warning-capture can break existing suites in the docs and CHANGELOG
Related to discussion in #2430
2017-05-25 21:19:08 -03:00
wanghui
c39689da41 Correct warnings with unicode message. 2017-05-25 17:59:42 +08:00
Bruno Oliveira
17f64704c2 Merge remote-tracking branch 'upstream/features' 2017-05-23 14:20:12 -03:00
Ronny Pfannschmidt
f9953fbe7c Merge pull request #2425 from nicoddemus/publish-task
Create task for publishing a release
2017-05-23 10:46:48 +02:00
Ronny Pfannschmidt
0ea80eb63c Merge pull request #2428 from The-Compiler/param-id-docs
Add docs for id= with pytest.param
2017-05-23 10:30:54 +02:00
Ronny Pfannschmidt
38ebf8dd10 Merge pull request #2429 from The-Compiler/regenschauer
Make --cache-show output deterministic
2017-05-23 10:30:39 +02:00
Ronny Pfannschmidt
04b1583d10 Merge pull request #2426 from The-Compiler/fix-changelog
Fix up 3.1 changelog
2017-05-23 08:18:24 +02:00
Florian Bruhin
d9b93674c3 Make --cache-show output deterministic
This makes sure things don't jump around in the regenerated docs.
2017-05-23 08:01:39 +02:00
Florian Bruhin
7d6bde2496 Add docs for id= with pytest.param 2017-05-23 07:57:34 +02:00
Florian Bruhin
bd065a12bb Fix up 3.1 changelog 2017-05-23 07:40:39 +02:00
Bruno Oliveira
f9df750025 Update 3.1.0 release date 2017-05-22 19:39:17 -03:00
Bruno Oliveira
d343f9497c Merge branch 'release-3.1' 2017-05-22 19:10:06 -03:00
Bruno Oliveira
5192191c38 Create task for publishing a release 2017-05-22 19:06:53 -03:00
Bruno Oliveira
69343310c6 Merge pull request #2422 from pytest-dev/refactor-config
Refactor config
2017-05-20 10:00:12 -03:00
Jason R. Coombs
c9c2c34b44 Remove unused parameter 2017-05-20 04:39:45 -04:00
Jason R. Coombs
9beeef970e Parse the filename in the generator expression 2017-05-20 04:38:30 -04:00
Jason R. Coombs
43aa037ebd Reindent 2017-05-20 04:38:30 -04:00
Jason R. Coombs
2abf2070f2 Collapse nested for loops into a generator expression 2017-05-20 04:38:30 -04:00
Jason R. Coombs
ce0ff0040f Reindent and add docstring 2017-05-20 04:38:27 -04:00
Jason R. Coombs
6d2e11b7d1 Extract method for _mark_plugins_for_rewrite 2017-05-20 04:18:41 -04:00
Bruno Oliveira
9b48613baa Preparing release version 3.1.0 2017-05-19 18:12:59 -04:00
Bruno Oliveira
0ff7f5d0c6 Prepare CHANGELOG for version 3.1.0 2017-05-19 19:10:09 -03:00
Bruno Oliveira
36cf89a2de Merge remote-tracking branch 'upstream/master' into features 2017-05-19 18:01:56 -04:00
Bruno Oliveira
3a4d37248d Merge pull request #2414 from nicoddemus/revert-new-style-classes
Revert refactor of old-style to new-style classes
2017-05-19 18:58:46 -03:00
Bruno Oliveira
637550b249 Merge pull request #2418 from axil/master
small fix in an example from the docs
2017-05-18 12:24:52 -03:00
Lev Maximov
598aefc686 small fix in an example from the docs 2017-05-18 21:18:09 +07:00
Bruno Oliveira
7af0e6bda1 Merge pull request #2415 from flub/training
Remove past training
2017-05-17 20:57:50 -03:00
Floris Bruynooghe
f7247dc99d Remove past training
Leaving the sidebar as an example for in the future.
2017-05-17 22:47:51 +01:00
Bruno Oliveira
d86c89e193 Revert refactor of old-style to new-style classes
As discussed in the mailing list, unfortunately this might break APIs
due to the subtle differences between new and old-style classes (see #2398).

This reverts commit d4afa1554b from PR #2179.
2017-05-17 18:20:51 -03:00
Florian Bruhin
e484f4760f Merge pull request #2412 from pytest-dev/pytest-book-ref
Add a reference to Python testing book to talks docs
2017-05-17 22:52:13 +02:00
Bruno Oliveira
70bcd1fb7b Add a reference to Python testing book to talks docs 2017-05-17 17:17:19 -03:00
Ronny Pfannschmidt
6f407ef308 Merge pull request #2411 from nicoddemus/automate-pre-release
Automate pre release steps
2017-05-17 14:36:33 +02:00
Bruno Oliveira
feab3ba70f Implement tasks to improve release automation 2017-05-15 23:44:03 -03:00
Bruno Oliveira
00e7ee532e Fix minor regendoc issues 2017-05-15 21:57:04 -03:00
Bruno Oliveira
fe49c78f32 Merge remote-tracking branch 'upstream/master' into release-3.1 2017-05-15 21:56:44 -03:00
Bruno Oliveira
3c41349fe1 Merge pull request #2406 from RonnyPfannschmidt/regendoc-reduce-version-noise
regendoc: reduce version noise by replacing minor/patch with placeholders
2017-05-15 19:40:45 -03:00
Bruno Oliveira
bd708068ab Merge branch 'features' into regendoc-reduce-version-noise 2017-05-14 14:34:07 -03:00
Ronny Pfannschmidt
783670b84e Merge pull request #2274 from dmand/feat/junitxml/suite-name-option
Add `junit_suite_name` ini option
2017-05-13 19:10:29 +02:00
Ronny Pfannschmidt
03753ca201 intermediate state after attempt with the plain env, DONT MERGE 2017-05-13 13:25:52 +02:00
Bruno Oliveira
456925b604 Merge pull request #2395 from RonnyPfannschmidt/consider-all-modules
Consider all modules
2017-05-12 18:25:12 -03:00
Bruno Oliveira
f39f416c5d Improve tests a bit
Use a normal function instead of a lambda
Parametrize test about suite name option
2017-05-12 17:52:50 -03:00
Ronny Pfannschmidt
d1e44d16e7 regenerate docs from the pytest env 2017-05-12 22:51:20 +02:00
Dmitri Pribysh
2ab8d12fe3 Update changelog and add usage info 2017-05-12 17:48:50 -03:00
Dmitri Pribysh
c9282f9e94 Transition to using ini option for suite name 2017-05-12 17:48:50 -03:00
Dmitri Pribysh
bcfa6264f1 Update AUTHORS list 2017-05-12 17:48:50 -03:00
Dmitri Pribysh
204db4d1e2 Update Changelog 2017-05-12 17:48:50 -03:00
Dmitri Pribysh
fe7d89f033 Add '--junit-suite-name' CLI option 2017-05-12 17:48:50 -03:00
Ronny Pfannschmidt
c765fa6d04 add regendoc normaliz for pytest --version 2017-05-12 22:38:50 +02:00
Ronny Pfannschmidt
f1c4e2c032 regendoc: reduce version noise by replacing minor/patch with placeholders 2017-05-12 22:17:40 +02:00
Ronny Pfannschmidt
a92e397011 add changelog for fixing #2391 2017-05-12 18:39:45 +02:00
Ronny Pfannschmidt
b6125d9a13 Merge pull request #2397 from nicoddemus/announce-task
Introduce a task to generate the announcement file for releases
2017-05-11 15:12:12 +02:00
Bruno Oliveira
66ba3c3aa4 Introduce a task to generate the announcement file for releases 2017-05-09 23:50:08 -03:00
Ronny Pfannschmidt
7ee2db23df Merge pull request #2396 from johndgiese/patch-1
Clarify opening paragraph of parameterization docs
2017-05-09 21:36:50 +02:00
David Giese
52c67af63c Clarify opening paragraph of parameterization docs
- Fix a few small grammar mistakes
- Rewrite a few sentences to make them shorter and easier to read
2017-05-09 10:02:08 -04:00
Ronny Pfannschmidt
8bcf88ec12 try to consider all modules after registration as plugin 2017-05-05 11:16:05 +02:00
Florian Bruhin
daca618012 Merge pull request #2389 from nicoddemus/merge-master-into-features
Merge master into features
2017-05-04 10:33:00 +02:00
Bruno Oliveira
f3b359f5b8 Merge remote-tracking branch 'upstream/master' into merge-master-into-features
# Conflicts:
#	_pytest/capture.py
#	_pytest/compat.py
#	_pytest/python.py
#	testing/python/collect.py
#	testing/test_mark.py
2017-05-03 19:04:53 -03:00
Ronny Pfannschmidt
3fc917a261 Merge pull request #2385 from nicoddemus/anaconda-badge
Add badge for anaconda package version
2017-05-03 07:07:52 +02:00
Ronny Pfannschmidt
814ea9d62c Merge pull request #2387 from nicoddemus/trial-errors
Fix py35-trial environment
2017-05-03 06:52:12 +02:00
Bruno Oliveira
630cca2fba Fix py35-trial environment
After updating to twisted 17.1.0, again the trial tests started to fail; didn't investigate too deep, decided to just
no longer delete "zope" modules when cleaning up after pytester because it seems more zope modules keep
global state that shouldn't be discarded
2017-05-02 21:05:42 -03:00
Florian Bruhin
bfd2563b3a Merge pull request #2386 from robin0371/show-correct-msg
Issue #2383 - AssertionError with wrong number of parametrize arguments
2017-04-29 14:57:01 +02:00
Vitaly Lashmanov
60b8339166 Issue #2383 - Show the correct error message when collect "parametrize" func with wrong args and add test for this case. 2017-04-29 14:32:09 +03:00
Bruno Oliveira
34f488757f Add badge for anaconda package version 2017-04-28 12:51:40 -03:00
Bruno Oliveira
cccb2cc92b Merge pull request #1834 from RonnyPfannschmidt/setuptools-scm-take-2
second take at setuptools_scm
2017-04-27 09:10:23 -03:00
Bruno Oliveira
d7d2249d99 Merge pull request #2378 from szuliq/patch-1
Update docs
2017-04-26 20:55:52 -03:00
Ronny Pfannschmidt
a280e43949 fix import error 2017-04-26 15:57:55 +02:00
Krzysztof Szularz
f0533194ed Update fixture.rst
Remove yet another not needed `request` argument in fixture definition.
2017-04-26 10:31:53 +02:00
Krzysztof Szularz
a9b44c4529 Update docs
Remove not needed `request` arg in order to simplify the example.
2017-04-25 16:35:19 +02:00
Ronny Pfannschmidt
e02cb6d7ce restore setuptools_scm write_to usage 2017-04-23 16:59:08 +02:00
Florian Bruhin
314d4afa57 Merge pull request #2367 from nicoddemus/py36-official-travis
Test against py36 official release for consistency with other python versions
2017-04-21 23:19:20 +02:00
Bruno Oliveira
25371ddbfd Merge pull request #2315 from RonnyPfannschmidt/namespace-hook
remove pytest internal usage of the namespace hook
2017-04-21 16:24:20 -03:00
Bruno Oliveira
80225ce72c Merge pull request #2374 from Kodiologist/getmodpath-file-ext
Try not to assume a module's file extension is .py
2017-04-21 16:23:25 -03:00
Ronny Pfannschmidt
4242bf6262 use unknown to specify unknown versions 2017-04-20 21:46:58 +02:00
Kodi Arfer
dcefb287fc Try not to assume a module's file extension is .py 2017-04-19 12:26:56 -07:00
Ronny Pfannschmidt
2cf422733c restore linting, drop _pytest._version for check-manifest 2017-04-19 20:25:53 +02:00
Ronny Pfannschmidt
c0a51f5662 restore check-manifst functionality 2017-04-19 20:12:38 +02:00
Ronny Pfannschmidt
31e6fe8f52 HOWTORELEASE.tst: use restructuredtext autonumbering 2017-04-19 19:40:42 +02:00
Ronny Pfannschmidt
c3aee4b1e6 second take at setuptools_scm
since setuptools 18.6 fixes the issues with develop installs

https://github.com/pypa/setuptools/blob/master/CHANGES.rst#186

https://github.com/pypa/setuptools/issues/439
2017-04-19 19:40:42 +02:00
Florian Bruhin
581b463b60 Merge pull request #2372 from nicoddemus/pytest-dont-rewrite-docs
Document PYTEST_DONT_REWRITE
2017-04-19 13:49:12 +02:00
Bruno Oliveira
90be44c812 Document PYTEST_DONT_REWRITE
Fixes #2203
2017-04-19 08:19:19 -03:00
Ronny Pfannschmidt
80cabca21a Merge pull request #2292 from nicoddemus/defer-hook-checking
Verify hooks after collection completes
2017-04-19 13:04:03 +02:00
Bruno Oliveira
cac82e71d8 Improve item.warn handling of fslocation parameter
Just pass fslocation forward and let the hook implementer decide what to do with the parameter
2017-04-13 19:01:14 -03:00
Bruno Oliveira
6e2bbe88b1 Test against py36 official release for consistency with other python versions 2017-04-13 17:54:56 -03:00
Bruno Oliveira
d9a2e70155 Change LsofFdLeakChecker to emit a warning instead of failing when detecting leaked FDs
Related to #2366
2017-04-13 17:34:48 -03:00
Bruno Oliveira
7dfdfa5813 Merge pull request #2359 from pytest-dev/fix-2343
Fix #2343: Replace version checks by constants.
2017-04-12 07:58:15 -03:00
Michael Howitz
7d4ac14a31 Fix #2343: Replace version checks by constants.
This way they do not have to be recomputed at runtime.
2017-04-12 08:18:09 +02:00
Bruno Oliveira
731776702d Fix hook name in LsofFdLeakChecker 2017-04-11 21:55:12 -03:00
Bruno Oliveira
0baf5e1499 Fix test that expected "unknown hook" error on stderr 2017-04-11 21:55:12 -03:00
Bruno Oliveira
83c508eea3 Verify hooks after collection completes
Fix #1821
2017-04-11 21:55:12 -03:00
Bruno Oliveira
78ac1bf5d1 Merge pull request #2350 from nicoddemus/future-imports-rewrite
Ensure rewritten modules don't inherit __future__ flags from pytest
2017-04-11 20:59:05 -03:00
Bruno Oliveira
02da278894 Merge pull request #2357 from ojii/lastfailed-failedfirst
Changed behavior if --lf and --ff are both used.
2017-04-11 19:05:01 -03:00
Bruno Oliveira
1125786e78 Improve --lf/--ff test as commented during review 2017-04-11 17:55:55 -03:00
Jonas Obrist
08d83a5c6a updated changelog and authors files 2017-04-10 17:50:18 +09:00
Jonas Obrist
0ab85e7a9c Changed behavior if --lf and --ff are both used.
When using both --last-failed/--lf and --failed-first/--ff pytest would
run all tests with failed tests first (as if --lf was not provied). This
patch changes it so that when using both flags, only the last failed
tests are run. This makes it easier to set --ff as the default behavior
via the config file and then selectively use --lf to only run the last
failed tests.
2017-04-10 17:46:13 +09:00
Bruno Oliveira
47a2a77cb4 Merge pull request #2354 from shobute/patch-1
Corrected documentation typo in fixtures.py
2017-04-07 14:31:36 -03:00
Ben Lloyd
21f1c2b03f Update fixtures.py
Corrected "or or" typo in docstring (and made indentation consistent).
2017-04-07 16:48:38 +01:00
Bruno Oliveira
8c69d5c939 Merge pull request #1940 from skylarjhdownes/master
adding documentation about pointing pytest at source files
2017-04-06 23:40:15 -03:00
Bruno Oliveira
f2300fbab2 Fix links in docs 2017-04-06 23:29:41 -03:00
Bruno Oliveira
45852386e5 Fix small typo in docs 2017-04-06 23:02:47 -03:00
Bruno Oliveira
5462697924 Small formatting fixes to nose.rst 2017-04-06 23:01:26 -03:00
Bruno Oliveira
639c592f31 Add missing link in CHANGELOG 2017-04-06 22:59:24 -03:00
Skylar Downes
f7caa56a6b moved documentation of conftest.py hack to nose.rst 2017-04-06 18:01:03 -07:00
Skylar Downes
3aa4fb62d6 Merge branch 'master' into master 2017-04-06 16:35:38 -07:00
Bruno Oliveira
c734a2d8d5 Merge pull request #2352 from pytest-dev/fix-search-docs
Pin sphinx to 1.4 when generating docs to workaround search issues on RTD
2017-04-06 18:41:30 -03:00
Bruno Oliveira
44a3db3dc6 Pin sphinx to 1.4 when generating docs to workaround search issues on RTD
Fix #2302
2017-04-06 18:09:01 -03:00
Bruno Oliveira
1b5f898dc5 Ensure rewritten modules don't inherit __future__ flags from pytest
In a recent refactoring we enabled all __future__ features in pytest
modules, but that has the unwanted side effect of propagating those
features to compile()'d modules inside assertion rewriting, unless
we pass dont_inherit=False to compile().
2017-04-06 15:00:36 -03:00
Ronny Pfannschmidt
83b241b449 Merge pull request #2347 from reutsharabani/features
added option to unicode plugin name
2017-04-06 18:16:20 +02:00
Bruno Oliveira
24ac923938 Add CHANGELOG entry 2017-04-06 12:42:17 -03:00
reut
333ce9849d added acceptance test for unicode plugin names 2017-04-06 10:54:47 +00:00
reut
417b54abed added option to unicode plugin name 2017-04-05 13:03:11 +00:00
Ronny Pfannschmidt
144d90932e Merge pull request #2337 from nicoddemus/2336-unicode-tb
Fix exception formatting while importing test modules
2017-03-30 09:12:14 +02:00
Bruno Oliveira
a542ed48a2 Convert using utf-8 instead of ascii in safe_str()
This way we don't lose information and the returned string is
ascii-compatible anyway
2017-03-29 15:18:41 -03:00
Bruno Oliveira
58ac4faf0c Fix exception formatting while importing test modules
Fix #2336
2017-03-29 14:43:13 -03:00
Ronny Pfannschmidt
afb1778294 put in a singular namespace hook to work around the strange issue 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
ebeba79be3 remove the namespace hook from mark after the param feature merge 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
6165939b0d fix rebase mistakes 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
efe03400d8 fixup nose/pytest plugins 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
c9ab421398 fix python2 only import loop failure 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
147bb8aea5 correct setting pytest.config 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
7cdefce656 fix up oversights 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
4d31ea8316 add a comment explaining the modimport tests 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
bb750a7945 add missed file 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
92f6ab1881 fix all singular internal module imports and add a test for them 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
809c36e1f6 add a changelog note for pytest_namespace 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
23bc9815c4 remove pytest_namespace from _pytest.fixtures 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
ae234786ea remove pytest_namespace from _pytest.python 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
99c8f2d403 remove pytest_namespace from _pytest.main 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
61f418a267 hollow out pytest_namespace in _pytest.fixtures 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
9b58d6eaca prepare a own pytest.collect fake module in oder to remove the nested builtin namespaces 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
839c936153 _pytest.mark: fix unconfigure after bad configure, still potential bug 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
7d797b7dbf add a note about the deprecation of the pytest_namespace hook 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
9b755f6ec6 remove pytest_namespace from _pytest.skipping 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
90788defb2 remove pytest_namespace from _pytest.mark and fix latent pytest nesting bug 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
6a02cdbb35 remove pytest_namespace from _pytest/runner.py 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
c74103f395 remove pytest_namespace from recwarn and fixture decorators 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
794fd5658c remove pytest_namespace from _pytest/debugging.py 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
fab9b993f8 remove pytest_namespace from _pytest.freeze_support 2017-03-28 11:45:06 +02:00
Ronny Pfannschmidt
5818e65cf3 remove pytest_namespace from _pytest/assertion 2017-03-28 11:35:29 +02:00
Ronny Pfannschmidt
2a130daae6 Merge pull request #2072 from nicoddemus/integrate-pytest-warnings
Integrate pytest warnings
2017-03-22 17:10:04 +01:00
Bruno Oliveira
0c1c2580d0 Add CHANGELOG entry 2017-03-22 12:40:31 -03:00
Bruno Oliveira
74b54ac0ec Fix errors related to warnings raised on pypy test environment
For some reason pypy raises this warning in the line that the catch_warnings block was added:

______________________________ ERROR collecting  ______________________________
C:\ProgramData\chocolatey\lib\python.pypy\tools\pypy2-v5.4.1-win32\lib-python\2.7\pkgutil.py:476: in find_loader
    loader = importer.find_module(fullname)
c:\pytest\.tox\pypy\site-packages\_pytest\assertion\rewrite.py:75: in find_module
    fd, fn, desc = imp.find_module(lastname, path)
<builtin>/?:3: in anonymous
    ???
E   ImportWarning: Not importing directory 'c:\users\bruno\appdata\local\temp\pytest-of-Bruno\pytest-3192\testdir\test_cmdline_python_package0' missing __init__.py
2017-03-21 22:32:41 -03:00
Bruno Oliveira
2c730743f1 Fix errors related to warnings raised by xdist
- pytester was creating a 'pexpect' directory to serve as temporary dir, but due to the fact that
   xdist adds the current directory to sys.path, that directory was being considered as candidate
   for import as a package. The directory is empty and a warning was being raised about
   it missing __init__ file, which is now turned into an error by our filterwarnings config
   in pytest.ini.

- Decided to play it safe and ignore any warnings during `pytest.importorskip`.

- pytest-xdist and execnet raise two warnings which should be fixed upstream:
   pytest-dev/pytest-xdist/issues/133
2017-03-21 22:17:07 -03:00
Bruno Oliveira
916d272c44 Fix test on linux 2017-03-20 23:44:50 -03:00
Bruno Oliveira
eabe3eed6b Add docs for the warnings functionality 2017-03-20 23:35:01 -03:00
Bruno Oliveira
fa56114115 Clean up warnings generated by pytest's own suite 2017-03-20 22:13:17 -03:00
Bruno Oliveira
d027f760c0 Avoid displaying the same warning multiple times for an item 2017-03-20 20:40:53 -03:00
Bruno Oliveira
3373e02eae Add __future__ imports to warnings module 2017-03-20 20:06:01 -03:00
Bruno Oliveira
9f85584656 Merge remote-tracking branch 'upstream/features' into integrate-pytest-warnings 2017-03-20 19:59:05 -03:00
Florian Bruhin
de8607deb2 Merge pull request #1921 from RonnyPfannschmidt/marked-value
introduce pytest.Marked as holder for marked parameter values
2017-03-20 10:54:12 +01:00
Ronny Pfannschmidt
e8a1b36c82 add changelog 2017-03-20 10:21:47 +01:00
Ronny Pfannschmidt
6cfe087261 Merge pull request #2320 from pawelad/2239/exit-code-docs
Added 'Possible exit codes' section to docs (#2239)
2017-03-20 06:22:23 +01:00
Paweł Adamczak
8b57aaf944 Added 'Paweł Adamczak' to AUTHORS 2017-03-19 18:38:41 +00:00
Paweł Adamczak
d58bc14645 Added 'Possible exit codes' section to docs (#2239) 2017-03-19 18:34:43 +00:00
Ronny Pfannschmidt
e368fb4b29 implement pytest.param
this allows a clear addition of parameterization parameters that carry along marks
instead of nesting multiple mark objects and destroying the possibility of creating
function valued parameters,
it just folders everything together into one object carrfying parameters, and the marks.
2017-03-17 16:53:43 +01:00
Ronny Pfannschmidt
a122ae85e9 Merge pull request #2316 from nicoddemus/add-future-imports
Add __future__ imports to all pytest modules
2017-03-17 13:41:46 +01:00
Bruno Oliveira
4d947077bb Fix test in py26 that expected a floor division error message 2017-03-16 23:07:03 -03:00
Bruno Oliveira
e5021dc9dc Replace py.builtin.print_() calls by builtin print() function 2017-03-16 22:46:51 -03:00
Bruno Oliveira
42a5d6bdfa Add __future__ imports to all pytest modules
This prevents silly errors from creeping in Python 2 when testing in Python 3
2017-03-16 22:45:40 -03:00
Bruno Oliveira
7684b3af7b Recommend using py36 for testing on CONTRIBUTING 2017-03-16 22:20:38 -03:00
Bruno Oliveira
78194093af Improve warning representation in terminal plugin and fix tests 2017-03-16 21:57:32 -03:00
Bruno Oliveira
be5db6fa22 Capture warnings around the entire runtestprotocol
This is necessary for the warnings plugin to play nice with the
recwarn fixture
2017-03-16 21:54:41 -03:00
Bruno Oliveira
0baed781fe Merge remote-tracking branch 'upstream/features' into integrate-pytest-warnings 2017-03-16 20:02:06 -03:00
Bruno Oliveira
337f891d78 Fixed tests 2017-03-16 20:01:47 -03:00
Bruno Oliveira
5482dfe0f3 Merge pull request #2303 from nicoddemus/recwarn-refactor
Refactor recwarn to use warnings.catch_warnings instead of custom code
2017-03-15 12:27:31 -03:00
Bruno Oliveira
75ec893d75 Merge pull request #2297 from nicoddemus/init-files-docs
Attempt to clarify the confusion regarding __init__ files and unique test names
2017-03-15 10:53:09 -03:00
Bruno Oliveira
76df77418d Merge pull request #2313 from nicoddemus/DontReadFromInput-exceptions
Dont read from input exceptions
2017-03-15 10:51:13 -03:00
Bruno Oliveira
55b891ddd0 Merge pull request #2312 from nicoddemus/merge-master-into-features-post-3.0.7
Merge master into features post 3.0.7
2017-03-14 23:26:43 -03:00
Bruno Oliveira
aad4946fb6 Move CHANGELOG entry for #2276 to 3.0.8 2017-03-14 18:58:28 -03:00
Xander Johnson
9062fbb9cc Add AUTHORS & CHANGELOG 2017-03-14 18:55:58 -03:00
Xander Johnson
dc6890709e Change ValueError to io.UnsupportedOperation in capture.py. Resolves issue #2276 2017-03-14 18:55:58 -03:00
Bruno Oliveira
272aba98e2 Mention the src layout as recommended practice 2017-03-14 18:39:02 -03:00
Bruno Oliveira
6c9011c12f Merge branch 'master' into merge-master-into-features-post-3.0.7 2017-03-14 18:10:23 -03:00
Bruno Oliveira
fa15ae7545 Post 3.0.7 release handling 2017-03-14 18:07:44 -03:00
Bruno Oliveira
5056d8cbe8 Merge pull request #2304 from nicoddemus/release-3.0.7
Release 3.0.7
2017-03-14 18:03:44 -03:00
Bruno Oliveira
4a9348324d Add more information to test-layout docs as discussed during PR 2017-03-14 07:59:01 -03:00
Ronny Pfannschmidt
5e52a4dda4 Merge pull request #2307 from nicoddemus/clarify-record-xml-property
Clarify that record_xml_property is experimental, not junitxml
2017-03-14 09:39:12 +01:00
Bruno Oliveira
92b49d246e Clarify that record_xml_property is experimental, not junitxml
Related to #2306
2017-03-13 23:04:44 -03:00
Bruno Oliveira
90c934e25e Include release 3.0.7 announce in index.rst 2017-03-13 18:59:15 -04:00
Bruno Oliveira
3c07072bfd Fix test_recwarn in Python 3.6
No longer test for implementation details of recwarn since warnings.catch_warnings has changed
significantly in 3.6.
2017-03-13 19:52:35 -03: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
Bruno Oliveira
22864b75ee Refactor recwarn to use warnings.catch_warnings instead of custom code
Since we dropped 2.5, we can now use warnings.catch_warnings to do the
"catch warnings" magic for us, simplifying the code a bit.
2017-03-13 19:28:36 -03:00
Bruno Oliveira
d1ea7c8cc8 Merge pull request #2301 from nicoddemus/merge-master-into-features
Merge master into features
2017-03-12 12:32:44 -03:00
Bruno Oliveira
1e0cf5ce4d Merge remote-tracking branch 'upstream/master' into merge-master-into-features
# Conflicts:
#	AUTHORS
#	CHANGELOG.rst
#	_pytest/pytester.py
2017-03-10 15:54:05 -03:00
Bruno Oliveira
581857aab6 Fix typo 2017-03-09 20:46:22 -03:00
Bruno Oliveira
841f731707 Attempt to clarify the confusion regarding __init__ files and unique test names
Fix #529
2017-03-09 20:41:33 -03: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
Bruno Oliveira
272afa9422 Display node ids and the warnings generated by it
The rationale of using node ids is that users can copy/paste it to run a chosen test
2017-03-04 20:53:42 -03:00
Bruno Oliveira
bddb922f7b Rename internal option to disable_warnings 2017-03-04 16:32:10 -03:00
Bruno Oliveira
de09023e45 Also capture warnings during setup/teardown 2017-03-04 16:15:03 -03:00
Bruno Oliveira
e24081bf76 Change warning output 2017-03-04 15:59:20 -03: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
Ronny Pfannschmidt
0c94f517a1 Merge pull request #2236 from KKoukiou/junitxml-change-schema
Change junitxml.py to produce results that comply with Junitxml schema
2017-03-02 17:26:11 +01:00
Katerina Koukiou
26e50f1162 junitxml: adjust junitxml output file to comply with JUnit xsd
Change XML file structure in the manner that failures in call and errors
in teardown in one test will appear under separate testcase elements in
the XML report.
2017-03-02 15:10:25 +01: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
Bruno Oliveira
0f3d7acdc4 Merge pull request #2266 from asottile/capture_v2
Make capsys more like stdio streams in python3. Resolves #1407.
2017-02-24 20:18:55 -03:00
Anthony Sottile
8b598f00e9 Make pytester use pytest's capture implementation 2017-02-23 17:46:28 -08:00
Anthony Sottile
6ba3475448 Make capsys more like stdio streams in python3. Resolves #1407. 2017-02-23 17:46:27 -08: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
Floris Bruynooghe
44ad369c17 Merge pull request #2263 from nicoddemus/revert-pluggy
Revert subclassing explicitly from object introduced by accident in #2260
2017-02-19 16:18:38 -03:00
Anthony Sottile
5fd010c4c3 Simplify travis.yml with tox environment variables 2017-02-19 09:02:35 -08:00
Bruno Oliveira
82785fcd40 Use warnings.catch_warnings instead of WarningsRecorder
This has the benefical side-effect of not calling the original
warnings.showwarnings function, which in its original form
only writes the formatted warning to sys.stdout.

Calling the original warnings.showwarnings has the effect that nested WarningsRecorder all catch the warnings:

with WarningsRecorder() as rec1:
    with WarningsRecorder() as rec2:
        warnings.warn(UserWarning, 'some warning')

(both rec1 and rec2 sees the warning)

When running tests with `testdir`, the main pytest session would then see the warnings created by
the internal code being tested (if any), and the main pytest session would end up with warnings as well.
2017-02-18 13:08:14 -02:00
Bruno Oliveira
a7643a5fbe Merge branch 'features' into integrate-pytest-warnings 2017-02-18 11:03:15 -02:00
Bruno Oliveira
f1900bbea6 Revert subclassing explicitly from object introduced by accident in #2260 2017-02-18 10:34:41 -02: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
abd6ad3751 Merge pull request #2260 from MichalTHEDUDE/feature/NewStyleClasses-2147
New-style classes implemented for python 2.7 - #2147
2017-02-16 19:05:09 -02:00
Michal Wajszczuk
fb0b90646e New-style classes implemented for python 2.7 - #2147 2017-02-16 20:28:17 +01: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
da828aac05 Merge pull request #2253 from The-Compiler/norecursedirs
Add venv to the default norecursedirs
2017-02-15 18:40:38 -02: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
Florian Bruhin
91c6bef77a Add venv to the default norecursedirs
venv (without a dot) is commonly used as a name for a virtualenv directory, and
we don't want to collect that.
2017-02-15 14:55:12 +01: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
Bruno Oliveira
208fae5bf0 Merge pull request #2227 from Kriechi/raises-info
add matching the error message to pytest.raises
2017-02-03 00:56:35 -02:00
Bruno Oliveira
abbff681ba Fix '{0}' format for py26 2017-02-02 18:01:44 -02:00
Thomas Kriechbaumer
43662ce789 allow error message matching in pytest.raises 2017-02-02 19:52:33 +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
Ronny Pfannschmidt
3b47cb45e6 Merge pull request #2222 from RonnyPfannschmidt/features
merge master into features
2017-01-26 13:48:10 +01:00
Ronny Pfannschmidt
3f30c22894 fix changelog merge mistake 2017-01-26 13:03:29 +01:00
Ronny Pfannschmidt
713bdc1f9f merge master into features 2017-01-26 12:00:52 +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
Bruno Oliveira
34e98bce0a Merge pull request #2198 from unsignedint/make-parametrize-enhancement
Enhancement to `make_parametrize_id`hook function
2017-01-25 21:37:18 -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
Ravi Chandra
0e58c3fa80 updates for PR review #2198 2017-01-21 16:47:49 +13:00
Ravi Chandra
c848d0a771 Pass parameter name to make_parametrize_id hook function 2017-01-21 16:46:45 +13: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
88f7befabb Merge pull request #2209 from RonnyPfannschmidt/bugfix-2208/get_real_func_loop_limit
fixes #2208 by introducing a iteration limit
2017-01-19 21:35:47 -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
250597d468 get_real_func: use saferepr when formatting the error message 2017-01-19 13:05:58 +01:00
Ronny Pfannschmidt
123289a88e fixes #2208 by introducing a iteration limit 2017-01-19 11:38:15 +01: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
Ronny Pfannschmidt
6c011f43e9 Merge pull request #2179 from mandeep/new-style-classes
Refactored old style classes to new style classes
2017-01-10 16:08:24 +01:00
mandeep
e412ea1d5a Added name to AUTHORS and change to CHANGELOG 2017-01-10 07:58:22 -06:00
mandeep
d4afa1554b Refactored old style classes to new style classes 2017-01-08 22:52:42 -06: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
Loïc Estève
3494dd06fe Remove duplicate target in rst 2017-01-03 10:57:19 -02:00
Loïc Estève
9e9547a9e4 Simplify condition 2017-01-03 10:57:19 -02:00
Loïc Estève
7930a8373d Newline for flake8 2017-01-03 10:57:19 -02:00
Loïc Estève
0bd8159b60 Add a test when multiple classes are specified in warns 2017-01-03 10:57:19 -02:00
Bruno Oliveira
56d1858ea2 Remove duplicate '@lesteve' link from CHANGELOG 2017-01-03 10:57:19 -02:00
Loïc Estève
6fd0394c63 pytest.warns checks for subclass relationship
rather than class equality. This makes it more similar to
pytest.raises.
2017-01-03 10:57:19 -02:00
Ronny Pfannschmidt
8f1450114f Merge pull request #2167 from fogo/parametrize-ids-silent-failure
No longer silently ignore errors in parametrize callable ids
2017-01-03 09:17:54 +01: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
Rafael Bertoldi
a9193a1531 No longer silently ignore errors in parametrize callable ids 2017-01-02 17:26:17 -02: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
964ccb93bb Merge pull request #2163 from nicoddemus/merge-master-into-features
Merge master into features
2016-12-28 22:21:06 -02:00
Bruno Oliveira
402fbe503a Merge branch 'master' into merge-master-into-features 2016-12-27 23:31:26 -02: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
669332b7e0 Merge pull request #2101 from wheerd/doctest-encoding
Added doctest encoding command line option
2016-11-30 17:43:42 -02:00
Florian Bruhin
9c224c94f0 Merge pull request #2099 from lwm/fixup-2007
Add missing `__test__` check for discovery
2016-11-30 20:23:40 +01:00
Wheerd
2edfc805af Added "versionadded" for doctest_encoding ini option to docs. 2016-11-30 18:01:00 +01:00
Luke Murphy
f5afd8cb54 Add missing __test__ check for test discovery. 2016-11-30 17:05:42 +01:00
Manuel Krebber
f8fef07b4c Fixed the tests for python 2.6 2016-11-30 14:19:07 +01:00
Manuel Krebber
b7fb9fac91 Fixed the documentation for doctest_encoding. 2016-11-30 14:17:54 +01:00
Manuel Krebber
1f62e5b5a0 Added CHANGELOG entry and myself to AUTHORS. 2016-11-30 11:50:11 +01:00
Manuel Krebber
c043bbb854 Changed the doctest_encoding option to an ini option.
Parametrized the tests for it.
2016-11-30 11:43:33 +01:00
Manuel Krebber
929912de29 Changed the tests to pass on python 2 as well. 2016-11-29 14:51:17 +01:00
Manuel Krebber
d254c6b0ae Added some tests for --docstring-encoding option. Added option to specify encoding for internal testdir._makefile() for the tests. 2016-11-29 12:29:16 +01:00
Manuel Krebber
ed977513ec Added a console option to specify the encoding to use for doctest files. Defaults to UTF-8. 2016-11-29 12:29:14 +01: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
Ronny Pfannschmidt
36eb5b36d1 Merge pull request #2096 from nicoddemus/merge-master-into-features
Merge master into features
2016-11-27 20:50:08 +01:00
Bruno Oliveira
b30a6d22c5 Merge branch 'master' into merge-master-into-features 2016-11-27 17:30:40 -02: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
Bruno Oliveira
bd343ef757 Merge remote-tracking branch 'upstream/features' into integrate-pytest-warnings 2016-11-22 14:35:39 -02:00
Bruno Oliveira
5ce551e469 Merge pull request #2075 from pytest-dev/master
Merge master into features after fixing flake8 errors
2016-11-22 14:10:31 -02: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
26ca5a702e Add tests and integrated the original code into the core 2016-11-21 08:26:43 -02:00
Bruno Oliveira
1da1906483 Rename code to _pytest.warnings and delete old files from the repository 2016-11-21 07:38:12 -02:00
Bruno Oliveira
9db32aea48 Merge c:\pytest-warnings\ into integrate-pytest-warnings 2016-11-21 07:34:24 -02:00
Bruno Oliveira
e31421a5d2 Moving all stuff to a subdirectory to try to retain history 2016-11-21 07:27:26 -02: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
Floris Bruynooghe
75740337d1 Merge pull request #2060 from pytest-dev/master
Merge master into features due to recent CI updates
2016-11-13 18:18:38 -08:00
Bruno Oliveira
6876ba9ba6 Merge pull request #1995 from mattduck/feat/restructure-assert-truncation
Restructure truncation of assertion messages
2016-11-13 19:07:35 -02: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
0fab78ee8f Merge pull request #2054 from nicoddemus/merge-master-features
Merge master into features after 3.0.4 release
2016-11-11 22:39:13 +01: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
efc54b2e56 Merge branch 'master' into merge-master-features 2016-11-11 18:56:53 -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
d49e9e5562 Merge pull request #2014 from RonnyPfannschmidt/warning-record-namedtuple
turn RecordedWarning into a namedtuple
2016-11-01 19:24:44 -02: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
b3c337db00 add changelog entry and documentation note about RecordedWarning 2016-10-24 15:28:35 +02:00
Ronny Pfannschmidt
e9668d75b8 turn RecordedWarning into a namedtuple
fixes #2013
2016-10-24 15:23:53 +02:00
Ronny Pfannschmidt
377e649e61 local merge of #1967 - Change exception raised by capture.DontReadFromInput.fileno() 2016-10-24 12:47:55 +02: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
Florian Schulze
6ec0c3f369 Bump. 2016-10-24 12:10:49 +02:00
Florian Schulze
ce138060ac Prepare pytest-warnings 0.2.0. 2016-10-24 12:09:49 +02:00
Florian Schulze
f229b573fa Bump version, add changelog entry and move stuff around for added coverage reporting. 2016-10-24 12:08:21 +02:00
Florian Schulze
28621b0510 Merge pull request #2 from Carreau/filter-regex
Add a warning option which does not escape its arguments.
2016-10-24 11:51:15 +02:00
Matthias Bussonnier
bc94a51a96 Add a warning option which does not escape its arguments.
This is useful when to use regular expressions, like for example ignore
a bunch of dynamic messages
    --filterwarnigns 'ignore:Please use assert.* instead.:'

Or ignore all the warnings in a sub-backage
    --filterwarnigns 'ignore:::package.submodule.*'

This is also available in the ini file as the filterwarnigns options
2016-10-22 09:58:13 -07: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
9d00615bbf Merge remote-tracking branch 'upstream/master' into merge-master-into-features 2016-10-20 21:51:42 -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
Matthew Duck
acee88a118 Fix truncation tests: pyruntest() match
Fix issue with truncation tests for -vv and CI, where the test for
non-truncated output would return a positive match even on truncated output.
2016-10-16 20:54:51 +01: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
Matthew Duck
0061d9bd3d Fix flake8 (unused import, trailng whitespace) 2016-10-11 00:17:15 +01:00
Matthew Duck
b629da424e Restructure truncation of assertion messages
This addresses ref https://github.com/pytest-dev/pytest/issues/1954.

The current truncation for assertion explanations does not deal with long lines
properly:

- Previously if lines were too long it would display a "-n more lines"
  message.

- 999e7c6541 introduced a bug where long lines can
  cause index errors if there are < 10 lines.

Extract the truncation logic into its own file and ensure it can deal with
long lines properly.
2016-10-10 23:38:27 +01: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
4667b4decc Merge branch 'master' into features 2016-09-29 19:03:26 -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
Skylar Downes
b0c78c867d Update CHANGELOG.rst 2016-09-27 15:50:45 -07:00
Skylar Downes
3d211da9bd add existing test suite page to table of contents 2016-09-27 14:01:54 -07:00
Skylar Downes
1ab1962eb1 make issue #1934 reference a link 2016-09-27 13:53:31 -07: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
Skylar Downes
12ac3c7338 remove existing tests stuff, add link to new page
Moved the "Contributing tests to an existing project" section to it's own page.
2016-09-27 13:08:15 -07:00
Skylar Downes
7e2f66adc3 Create existingtestsuite.rst 2016-09-27 12:51:46 -07:00
Bruno Oliveira
654af0ba25 Merge remote-tracking branch 'upstream/master' into features 2016-09-26 19:32:53 -03:00
Vlad Dragos
acac78adc0 Add link to profile. 2016-09-26 16:09:25 +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
Vlad Dragos
3444796f3e Fix formating error. 2016-09-26 13:59:28 +03:00
Vlad Dragos
ff492ca73f Thanked my self in the change log :) 2016-09-26 13:27:41 +03:00
Vlad Dragos
8985c0be3e Change exception raised by DontReadFromInput.fileno() from ValueError to io.UnsupportedOperation 2016-09-26 13:15:35 +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
3fce78498f Mention #1952 on the CHANGELOG
Also created "New Features" and "Changes" sections.
2016-09-25 20:31:03 -03:00
Bruno Oliveira
5e96edd435 Merge pull request #1952 from davidszotten/pdbcls_without_pdb_on_fail
Pdbcls without pdb on fail
2016-09-25 20:24:45 -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
David Szotten
d75748ef6f test for calling set_trace with custom pdb cls 2016-09-21 09:45:26 +00:00
David Szotten
c7b4b8cf6f test 2016-09-21 09:45:23 +00:00
David Szotten
0ac85218d1 allow pdbcls without implying usepdb 2016-09-21 09:45:20 +00: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
887c097f8e Merge pull request #1951 from mattduck/feat/1512-dict-compare-output
Feat/1512 dict compare output
2016-09-19 17:34:09 +01:00
Floris Bruynooghe
01db0f1cd1 Merge pull request #1923 from RonnyPfannschmidt/mark-internal-value
use consistent inner repressentation for marks
2016-09-19 15:30:22 +01:00
Matthew Duck
4df74a5cfb Add AUTHORS and CHANGELOG for #1512 2016-09-19 15:29:37 +01:00
Matthew Duck
999e7c6541 Tidy formatting of assertion truncation
Part two of https://github.com/pytest-dev/pytest/issues/1512. Update the format
of the truncation message to help make it clear that pytest truncates the
entire assertion output when verbosity < 2.
2016-09-19 15:27:38 +01:00
Matthew Duck
dd64d823b9 Don't display dict common items if verbosity=1
Part one of https://github.com/pytest-dev/pytest/issues/1512.

If verbosity=1, assertion explanations are truncated at 10 lines. In this
situation, it's more important to tell the user which dictionary items are
different than which are the same.
2016-09-19 15:27:28 +01:00
Floris Bruynooghe
dc16fe2bb9 Merge junit-xml url attribute branch
Merge branch 'url_attr' of https://github.com/fushi/pytest into junitxml-url
2016-09-19 12:57:05 +01:00
Floris Bruynooghe
5b260d80f9 Merge pull request #1883 from RonnyPfannschmidt/kill-memoized-call
Kill memoized call
2016-09-19 12:47:52 +01: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
Skylar Downes
34117be98b Update goodpractices.rst 2016-09-15 16:45:35 -07:00
Skylar Downes
330a2f6784 Update getting-started.rst 2016-09-15 16:28:37 -07:00
Skylar Downes
f1faaea3fd Update CHANGELOG.rst 2016-09-15 15:22:53 -07:00
Skylar Downes
d781b76627 Update AUTHORS 2016-09-15 15:20:47 -07:00
Skylar Downes
81a733f2dc add how-to for getting started on existing project
ref #1937
2016-09-15 15:09:47 -07:00
Skylar Downes
07ad71e851 clarified purpose of pip install -e command
ref #1937
2016-09-15 14:55:54 -07:00
Skylar Downes
b4fd74c6ff add mention of setup.py develop 2016-09-15 14:10:57 -07:00
Skylar Downes
69f72c6f4b fix typo 2016-09-15 10:49:59 -07:00
Skylar Downes
383fc02ba6 fix spacing 2016-09-15 10:47:16 -07:00
Skylar Downes
d217984129 documenting how to point pytest at local code
Related to #1937
2016-09-15 10:46:15 -07: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
Ronny Pfannschmidt
45524241a5 mark: fix introduced linting error 2016-09-08 10:16:45 +02:00
Ronny Pfannschmidt
1812387bf0 Mark: fix python 3 compatibility 2016-09-08 10:03:45 +02:00
Ronny Pfannschmidt
10094a3f09 use consistent inner repressentation for marks 2016-09-08 09:52:22 +02: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
1c9bd9278e Merge pull request #1913 from flub/builtin-assertion
Remove BuiltinAssertionError
2016-09-05 16:53:13 +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
Floris Bruynooghe
28b1896e9a Remove BuiltinAssertionError
We used to have this when we where patching the real Python
AssertionError for use with reinterpret, but reinterpret is now
gone so we no longer need this as it is not used by rewrite.
2016-09-05 15:29:09 +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
e1674f60e7 remove memocollect anmd memoized_call 2016-09-05 14:41:28 +02:00
Ronny Pfannschmidt
e572c16d3f remove memoizedcall in Module 2016-09-05 14:41:28 +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
Florian Bruhin
98ac1dd34b Merge pull request #1902 from nicoddemus/features
Merge master into features after 3.0.2
2016-09-02 06:35:44 +02:00
Bruno Oliveira
f5d900d972 Merge remote-tracking branch 'upstream/master' into features 2016-09-01 23:07:49 -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
Bruno Oliveira
9d2149d9c0 Merge pull request #1884 from pytest-dev/master
merge master into features
2016-08-30 18:47:57 -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
John Towler
1b259f70f3 Testcase reports with a url attribute will now properly write this to junitxml 2016-08-25 13:08:51 -07: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
c5675d3efc Remove merge-conflict marker merged by accident
Unfortunately rst-lint didn't catch that
2016-08-23 23:43:05 -03:00
Bruno Oliveira
6359894fe4 Merge pull request #1859 from nicoddemus/merge-master-into-features
Merge master into features
2016-08-23 23:39:01 -03: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
7704f73db9 Merge branch 'master' into merge-master-into-features 2016-08-23 21:36:42 -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
db922403cc Bump version to 3.1.0.dev 2016-08-19 17:44:07 -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
Bruno Oliveira
c74ce371ab Add release announcement 2016-08-18 12:02:01 -04:00
Bruno Oliveira
7f18367582 Finalize CHANGELOG 2016-08-18 11:43:21 -04:00
Bruno Oliveira
a3e6c14da3 Bump version to 3.0.0 2016-08-18 11:41:10 -04:00
Florian Bruhin
be9356aeba Merge pull request #1817 from nicoddemus/regendoc-run
Run regendoc for 3.0 release
2016-08-18 15:31:03 +02:00
Bruno Oliveira
9ce30e0085 Run regendoc for 3.0 release 2016-08-18 08:27:16 -04:00
Bruno Oliveira
3748112a94 Merge pull request #1816 from nicoddemus/merge-master-into-features
Merge master into features
2016-08-18 08:48:01 -03:00
Bruno Oliveira
0334e75c30 Use "pytest" instead of "py.test" on trial environments 2016-08-18 08:37:55 -03:00
Bruno Oliveira
56df9fcc72 Tweak CHANGELOG: move "change" entry to the proper place 2016-08-17 23:08:13 -03:00
Bruno Oliveira
66673c0dd3 Remove obsolete docstring 2016-08-17 22:59:18 -03:00
Bruno Oliveira
030c42203d Fix conflicts in CHANGELOG 2016-08-17 22:58:12 -03:00
Bruno Oliveira
3ba475c0f2 Move internal _is_unittest_unexpected_success_a_failure to "compat" module
Fix #1815
2016-08-17 22:50:10 -03:00
Bruno Oliveira
463e6572c5 Merge branch 'master' into merge-master-into-features
Preparing for 3.0
2016-08-17 22:39:23 -03:00
Bruno Oliveira
3e685d6a8d Merge pull request #1795 from hackebrot/fix-report-outcome-for-xpass
WIP Change outcome to 'passed' for xfail unless it's strict
2016-08-17 22:18:06 -03:00
Bruno Oliveira
68ebf552a1 Merge remote-tracking branch 'upstream/master' into fix-report-outcome-for-xpass 2016-08-17 21:55:10 -03:00
Bruno Oliveira
a01cbce662 Merge pull request #1814 from nicoddemus/py35-trial-windows
Enable py35-trial testenv on Windows
2016-08-17 21:54:47 -03:00
Bruno Oliveira
0fb34cd2a1 Update CHANGELOG entries 2016-08-17 21:32:07 -03:00
Bruno Oliveira
224ef67374 Quick fix for tests in config depended on the current directory
When running those tests from pytest's root folder, they would
fail because they would end up picking pytest's own pytest.ini
2016-08-17 21:32:05 -03:00
Bruno Oliveira
4ed412eb59 unittest's unexpectedSuccess should work as non-strict xpass
Make sure tests for that behavior obtain the same return code
using either pytest or unittest to run the same file
2016-08-17 21:32:04 -03:00
Bruno Oliveira
92498109e4 Enable py35-trial testenv on Windows 2016-08-17 21:20:12 -03:00
Raphael Pierzina
dfc659f781 Fix sys.version_info expression in xfail marker 2016-08-17 23:32:56 +01:00
Raphael Pierzina
0173952961 Fix py3 xfail expression evaluation and parametrize strict 2016-08-17 23:15:14 +01:00
Raphael Pierzina
767c28d422 Fix broken test in test_junitxml 2016-08-17 22:32:27 +01:00
Raphael Pierzina
d1f2f779ee Use a better xfail reason 2016-08-17 22:31:56 +01:00
Raphael Pierzina
bb3d6d87b6 Merge branch 'master' into fix-report-outcome-for-xpass 2016-08-17 22:15:29 +01:00
Raphael Pierzina
018197d72a Fix broken test in test_skipping and add one for strict xfail 2016-08-17 22:14:51 +01:00
Raphael Pierzina
ea379e0e4f Fix test in test_junitxml and add one for strict 2016-08-17 22:02:54 +01:00
Florian Bruhin
789e4670e7 Merge pull request #1813 from nicoddemus/pytest-setup.cfg
Support [tool:pytest] in setup.cfg files
2016-08-17 20:33:57 +02:00
Florian Bruhin
c8ab79402c Merge pull request #1811 from nicoddemus/revert-invocation-fixtures
Revert invocation-fixtures code
2016-08-17 20:32:54 +02:00
Bruno Oliveira
ab86dea529 Support [tool:pytest] in setup.cfg files
Also deprecate [pytest] usage in setup.cfg files

Fix #567
2016-08-17 08:19:38 -03:00
Bruno Oliveira
707b6b5e3f Revert all invocation-fixtures code
Due to a serious regression found in #1794, it was decided to pull off
invocation features from 3.0 so it can be (hopefully) re-introduced
in 3.1
2016-08-17 08:12:55 -03:00
Florian Bruhin
09e647c7d9 Merge pull request #1812 from nicoddemus/deprecate-resultlog
Deprecate --resultlog cmdline option
2016-08-17 09:17:13 +02:00
Bruno Oliveira
f25771a101 Deprecate --resultlog cmdline option
Fix #830
2016-08-16 21:40:34 -03:00
Raphael Pierzina
55ec1d7f56 Update test_junitxml.py to interpret XPASS as passed 2016-08-15 23:58:16 +01:00
Bruno Oliveira
497152505e Add CHANGELOG entry for #1809 2016-08-15 19:31:00 -03:00
Bruno Oliveira
ca5957932b Merge pull request #1806 from blueyed/fix-off-by-one-error-with-warnings
Fix off-by-one error with lines from request.node.warn
2016-08-15 19:04:00 -03:00
Bruno Oliveira
d58a8e36d7 Merge pull request #1807 from blueyed/improve-multiline-error-format
Improve display of continuation lines with multiline errors
2016-08-15 19:03:35 -03:00
Bruno Oliveira
d3b855104c Merge pull request #1809 from blueyed/exitstatus-with-pytest_terminal_summary
Pass exitstatus to pytest_terminal_summary hook
2016-08-15 19:02:30 -03:00
Daniel Hahler
c163cc7937 Improve display of continuation lines with multiline errors
Fixes https://github.com/pytest-dev/pytest/issues/717.
Follow-up to https://github.com/pytest-dev/pytest/pull/1762.
2016-08-14 22:34:31 +02:00
Daniel Hahler
16cb5d01b1 Fix off-by-one error with lines from request.node.warn
The line numbers in `node.location` seem to be zero-based?!
2016-08-14 22:10:01 +02:00
Daniel Hahler
5b95ee3c19 Pass exitstatus to pytest_terminal_summary hook
This is useful to know if a testrun has been interrupted
(EXIT_INTERRUPTED).
2016-08-14 22:06:35 +02:00
Raphael Pierzina
225341cf2c Set wasxfail only for xpass w/o strict and else set longrepr 2016-08-13 00:00:51 +01:00
Raphael Pierzina
14a4dd0697 Extend test to verify longrepr in stdout 2016-08-12 23:31:38 +01:00
Raphael Pierzina
296f42a2c9 Treat unittest.expectedFailure pass as a failure 2016-08-12 23:18:36 +01:00
Raphael Pierzina
10a6ed1707 Update unittest test to expect failure for an unexpected success 2016-08-12 23:18:02 +01:00
Bruno Oliveira
34925a31a9 Merge pull request #1799 from cryporchild/junitxml-tests-tally-fix
Fix #1798 to include errors in total tests in junit xml output.
2016-08-08 10:43:38 -03:00
Christian Boelsen
c4d9c7ea55 Add thanks as requested. 2016-08-08 13:45:10 +01:00
Christian Boelsen
e4028b4505 Fix #1798 to include errors in total tests in junit xml output. 2016-08-08 13:35:49 +01:00
Floris Bruynooghe
99a4a1a784 Merge pull request #1791 from nicoddemus/ide-integration-1790
Internal adjustments for easier integration with IDEs
2016-08-07 23:50:50 +01:00
Bruno Oliveira
4ab2e57ebd Merge pull request #1797 from nicoddemus/merge-master-into-features
Merge master into features
2016-08-06 18:48:40 -03:00
Bruno Oliveira
802755ceed Merge remote-tracking branch 'upstream/master' into merge-master-into-features 2016-08-06 17:58:17 -03:00
Bruno Oliveira
ac5c39e534 Merge pull request #1796 from nicoddemus/fix-rootdir-common-ancestor
Fix rootdir common ancestor
2016-08-06 17:38:42 -03:00
Bruno Oliveira
21230aa017 Add CHANGELOG entry 2016-08-06 17:14:13 -03:00
Dave Hunt
eb08135280 Update documentation to describe expected rootdir behaviour 2016-08-06 19:35:40 +02:00
Daniel Hahler
a2891420de Fix determining rootdir from common_ancestor 2016-08-06 19:35:40 +02:00
Raphael Pierzina
4fc20d09fe Change outcome to 'passed' for xfail unless it's strict 2016-08-05 19:25:55 +01:00
Bruno Oliveira
1a79137d04 Add originalname attribute to Function
Related to #1790
2016-08-03 22:56:12 -03:00
Bruno Oliveira
530b0050b4 Improve TestReport.sections docs a bit
Related to #1790
2016-08-03 21:57:58 -03:00
Bruno Oliveira
ff296fd541 Add capstdout and capstderr attrs to TestReport
Related to #1790
2016-08-03 21:49:43 -03:00
Bruno Oliveira
08002ab75a Add longreprtext property to TestReport objects
Related to #1790
2016-08-03 21:49:28 -03:00
Bruno Oliveira
6759b042b5 Merge pull request #1789 from nicoddemus/regendoc-take-2
Regendoc take 2
2016-08-03 18:21:36 -03:00
Bruno Oliveira
8b8c698f1a Add more interpreter versions to multipython example 2016-08-03 16:48:49 -04:00
Bruno Oliveira
d28801d794 Make parametrize example deterministic 2016-08-03 16:48:11 -04:00
Bruno Oliveira
72df32f1fd Fix missing print() 2016-08-03 17:34:55 -03:00
Bruno Oliveira
701d5fc727 Regendoc after more fixes on features branch 2016-08-03 16:31:44 -04:00
Bruno Oliveira
6e3105dc8f Merge pull request #1787 from nicoddemus/fix-rewrite-conftest
Rewrite asserts in test-modules loaded very early in the startup
2016-08-03 16:10:55 -03:00
Bruno Oliveira
6711b1d6ab Rewrite asserts in test-modules loaded very early in the startup
Also now match modules which start with any of the names registered
using register_assert_rewrite as discussed in #1787

Fix #1784
2016-08-03 12:49:48 -03:00
Florian Bruhin
d5be6cba13 Merge pull request #1788 from nicoddemus/available-fixtures-sorted
Sort fixture names when a fixture lookup error occurs
2016-08-03 07:31:28 +02:00
Bruno Oliveira
277b6d3974 Sort fixture names when a fixture lookup error occurs 2016-08-02 19:45:31 -03:00
Bruno Oliveira
ea6191a0cd Merge pull request #1779 from RonnyPfannschmidt/deselect-no-reason
terminal: dont pretend to know the deselection reason
2016-08-02 08:38:17 -03:00
Floris Bruynooghe
9540106fe7 Merge pull request #1780 from nicoddemus/regen-pytest30
Run regen-docs for pytest 3.0
2016-08-02 12:07:16 +01:00
Ronny Pfannschmidt
1c8fe962f3 add changelog entry 2016-08-02 10:51:10 +02:00
Ronny Pfannschmidt
48f4e18280 fix deselect tests to match reason removal 2016-08-02 10:43:25 +02:00
Bruno Oliveira
21a90c8c50 Run regendoc again 2016-08-01 20:12:00 -04:00
Bruno Oliveira
eed21e06db Sort yml items to get same results for regendoc runs 2016-08-01 20:09:35 -04:00
Bruno Oliveira
a6b2732507 Pass list of params to pytest.main() in docs 2016-08-01 20:09:35 -04:00
Bruno Oliveira
946466abf4 Run regen-docs for pytest 3.0 2016-08-01 20:09:35 -04:00
Raphael Pierzina
3cd2e37c55 Merge pull request #1783 from nicoddemus/inv-scoped-fixture-msg
Strip invocation-scope suffix when displaying fixture lookup error
2016-08-02 01:08:25 +01:00
Bruno Oliveira
553dc2600f Strip invocation-scope suffix when displaying fixture lookup error 2016-08-01 20:34:56 -03:00
Raphael Pierzina
226f2795ba Merge pull request #1782 from nicoddemus/invocation-fixtures-help
invocation-scoped fixtures show up once with --fixtures
2016-08-01 23:21:28 +01:00
Bruno Oliveira
b380eb5b34 Merge pull request #1781 from nicoddemus/highlight-file-loc
Highlight the path of file location in error report
2016-08-01 19:18:52 -03:00
Bruno Oliveira
44ecf2ab2f invocation-scoped fixtures show up once with --fixtures 2016-08-01 18:48:29 -03:00
Bruno Oliveira
31c5194562 Fix broken test in py3k 2016-08-01 18:35:42 -03:00
satoru
3c8222f1db Highlight the path of file location in error report
So that it's more obvious when we need to copy the file path.
2016-08-01 17:42:20 -03:00
Ronny Pfannschmidt
ac215e9cff terminal: dont pretend to know the deselection reason
this addresses #1372 - we pretend we know the deselection reason from internal plugins and ignore 3rd party/local reasons
2016-08-01 13:50:59 +02:00
Bruno Oliveira
aa145fa83e Add 'invocation' scope option to fixture docstring 2016-07-29 12:47:30 -03:00
Bruno Oliveira
76fbc6379f Fix deprecated directive in docstring 2016-07-29 12:39:48 -03:00
Bruno Oliveira
80508203b0 Merge pull request #1776 from nicoddemus/pytest-30-version
Set version to 3.0.0.dev1
2016-07-28 21:57:13 -03:00
Bruno Oliveira
eaf8d9ce19 Set version to 3.0.0.dev1
For a long time now we've considering the next version to be 3.0.0
2016-07-28 21:30:16 -03:00
Floris Bruynooghe
510a6083ba Merge pull request #1758 from nicoddemus/deprecated-module
Add deprecation module to centralize deprecation messages and bits of…
2016-07-28 22:36:55 +01:00
Florian Bruhin
ffb583ae91 Merge pull request #1773 from nicoddemus/fix-freeze
Use PyInstaller for freeze test env
2016-07-27 15:06:54 +02:00
Bruno Oliveira
ae9d3bf886 Freeze docs: PyInstaller hook and wording
As discussed during the review, suggest in general
to use PyInstaller and just mention pytest.freeze_includes()
in less detail on how to actually use it, because it varies
from tool to tool.
2016-07-27 09:15:40 -03:00
Florian Bruhin
7b1520687e Merge pull request #1771 from nicoddemus/sort-links-changelog
Sort link refs in CHANGELOG
2016-07-27 06:26:45 +02:00
Florian Bruhin
fd765f854c Merge pull request #1772 from nicoddemus/pdf-link
Fix pdf links in docs and point to docs.pytest.org in README
2016-07-27 06:25:41 +02:00
Bruno Oliveira
ed36d627e4 Use PyInstaller for freeze test env
cx_freeze doesn't seem to be very well supported in Python 3.5.

Using pyinstaller instead and rename environment to "freeze" which
is a more generic term for freezing python code into standalone
executables.

Fix #1769
2016-07-26 22:02:37 -03:00
Bruno Oliveira
9a68681719 Point doc links in README to docs.pytest.org 2016-07-26 20:25:55 -03:00
Bruno Oliveira
0b8a91b858 Fix pdf links in the documentation
Fix #1436
2016-07-26 20:20:22 -03:00
Bruno Oliveira
5565c1f4ae Sort link refs in CHANGELOG 2016-07-26 20:11:49 -03:00
Florian Bruhin
c40dcb3c18 Merge pull request #1768 from ioggstream/1609-fix-description
fix keep-duplicates help line.
2016-07-26 11:34:06 +02:00
Roberto Polli
05728d1317 fix keep-duplicates help line. 2016-07-26 09:53:12 +02:00
Florian Bruhin
b4ad4cc46e Merge pull request #1767 from nicoddemus/merge-master
Merge master into features
2016-07-26 08:44:11 +02:00
Bruno Oliveira
c2864aba3d Merge branch 'master' into merge-master
# Conflicts:
#	AUTHORS
#	CHANGELOG.rst
#	_pytest/monkeypatch.py
#	_pytest/python.py
2016-07-25 19:06:29 -03:00
Bruno Oliveira
9cf09cda7b Remove some comments and improved changelog 2016-07-25 18:41:03 -03:00
Bruno Oliveira
eb5b163698 Merge branch '1609-features' of https://github.com/ioggstream/pytest into features 2016-07-25 18:37:55 -03:00
Bruno Oliveira
d911bfcb8a Merge branch 'issue634-scopes' of https://github.com/Stranger6667/pytest
# Conflicts:
#	CHANGELOG.rst
2016-07-25 18:26:50 -03:00
Bruno Oliveira
8f29ce26e9 Merge branch 'mark_missing_fixture_error' of https://github.com/eolo999/pytest 2016-07-25 18:20:17 -03:00
Bruno Oliveira
6c8b0a28e1 Add deprecation module to centralize deprecation messages and bits of code 2016-07-25 18:14:39 -03:00
Dmitry Dygalo
d72afe7e08 Fixed scope override inside metafunc.parametrize. Fixes #634 2016-07-25 12:42:50 +02:00
Roberto Polli
ab6aef1d1f feature: default behavior now is to ignore duplicate paths specified from the command line. Use --keep-duplicates to retain duplicate paths. 2016-07-25 12:41:58 +02:00
Florian Bruhin
a2b04d02c2 Merge pull request #1759 from Stranger6667/issue1579-invalid-class
Fixed collection of classes with custom ``__new__`` method. Fixes #1579.
2016-07-25 12:27:51 +02:00
Dmitry Dygalo
f7ad173fee Fixed collection of classes with custom `__new__` method 2016-07-25 11:33:37 +02:00
Ronny Pfannschmidt
d37af20527 Merge pull request #1765 from The-Compiler/1763-cleanup
Cleanups for #1763
2016-07-25 10:31:06 +02:00
Florian Bruhin
a309a571d9 Cleanups for #1763 2016-07-25 10:17:46 +02:00
Edoardo Batini
e9d729bd46 drop parenthesis around GH issue number 2016-07-25 10:11:37 +02:00
Bruno Oliveira
c9a2e611ce Merge pull request #1763 from tomviner/issue1210-exit-msg
Fix #1210 display msg for early calls to exit
2016-07-24 13:05:44 -03:00
Bruno Oliveira
a24146dd3c Merge pull request #1757 from tramwaj29/improved-message-when-not-using-parametrized-variable
Improved message when not using parametrized variable
2016-07-24 13:02:03 -03:00
Bruno Oliveira
7862517c28 Merge pull request #1760 from blueyed/followup-pr1718-remove-newline
Followup to #1718: style/formatting
2016-07-24 13:00:14 -03:00
Tom Viner
42adaf5a61 Fix #1210 display msg for early calls to exit 2016-07-24 14:16:34 +02:00
JJ
4aede6faa6 fixed conflicts 2016-07-24 12:10:32 +02:00
JJ
d000f2536a added a test for when the indirect is just a string 2016-07-24 10:47:06 +02:00
Edoardo Batini
0ae77be9f0 Add new target links in CHANGELOG 2016-07-24 00:46:06 +02:00
Daniel Hahler
5c5d7e05f7 Followup to #1718: style/formatting 2016-07-24 00:21:42 +02:00
Edoardo Batini
f450e0a1db Thanks to Tom Viner for his guidance during EuroPython2016 sprint 2016-07-24 00:06:16 +02:00
Edoardo Batini
fabe8cda2f Thanking myself in CHANGELOG 2016-07-23 23:59:34 +02:00
Edoardo Batini
3c4158ac35 Add changelog entry for this bugfix branch 2016-07-23 23:51:11 +02:00
Edoardo Batini
e00199212c Add myself to the AUTHORS 2016-07-23 23:49:44 +02:00
Edoardo Batini
e9a67e6702 Adjust test involving FixtureLookupErrorRepr
I added a starting 'E' to the expected error messages.

The tests were still passing after the previous patch but I think it's
better to have stricter tests.
2016-07-23 23:45:07 +02:00
Edoardo Batini
6799a47c78 Start FixtureLookupErrorRepr with an 'E' 2016-07-23 23:43:34 +02:00
Bruno Oliveira
655df7f839 Merge pull request #1755 from diegorusso/master
Testcase for overriding autouse fixture with a parametrized fixture.
2016-07-23 12:53:24 -03:00
Bruno Oliveira
9891593413 Merge pull request #1754 from hartym/1749_doctest_report_format
Doctest report format option (#1749)
2016-07-23 12:52:54 -03:00
JJ
bbc7f3a631 updated changelog, resolve #1539 2016-07-23 16:57:49 +02:00
Diego Russo
1704b7d265 Test case for overriding autouse fixtures
Test case for overriding autouse fixture with a parametrized fixture.
The test covers the problem explained in the issue 1601
Adding Diego Russo to AUTHORS
2016-07-23 16:53:39 +02:00
JJ
3631719050 added myself to authors 2016-07-23 16:51:55 +02:00
JJ
f26fa5a441 changed error message for unused parametrize name 2016-07-23 16:49:20 +02:00
Romain Dorgueil
94731fc2a1 Changes variable name so it better describes what it does now. 2016-07-23 16:26:33 +02:00
Romain Dorgueil
51fa244650 Cleaner implementation of #1749. 2016-07-23 16:18:12 +02:00
Romain Dorgueil
d5a70acd48 Simplify test in test_doctest_report_none_or_only_first_failure. 2016-07-23 15:58:13 +02:00
Bruno Oliveira
018acc6bae Explain why thanks yourself in the CHANGELOG 2016-07-23 10:44:38 -03:00
Romain Dorgueil
f8f690de64 adds the versionadded flag in docs (#1749) 2016-07-23 15:30:06 +02:00
Romain Dorgueil
e229a27e8b using @pytest.mark.parametrize instead of calling one test many times from another as suggested by @nicoddemus in pr #1754 2016-07-23 15:21:59 +02:00
Romain Dorgueil
ec7695e15d adds a bit of doctest hint on why the key and value getters are separate functions. 2016-07-23 15:19:18 +02:00
Romain Dorgueil
1a33025a76 Refactors test to be in its own class, as discussed with @nicoddemus. 2016-07-23 15:16:23 +02:00
Romain Dorgueil
922a295729 fixes changelog, I think I got it 2016-07-23 15:15:17 +02:00
Romain Dorgueil
014ebc9202 Removed bug reference in changelog because it makes the linting fail. 2016-07-23 15:04:19 +02:00
Romain Dorgueil
87ca4b95fb Separate the option keys and value to avoid importing "doctest" (and tested things like "logging") for argument parsing (fixes #1749) 2016-07-23 14:50:24 +02:00
Romain Dorgueil
fd8e019cc1 Choose the doctest output format in case of failure, still work in progress as a few checks fail (related to #1749) 2016-07-23 14:40:46 +02:00
Romain Dorgueil
625b603f1f Implements an option to choose the doctest output format in case of failure. (fixes #1749) 2016-07-23 13:06:05 +02:00
Bruno Oliveira
38e0e08074 Merge pull request #1751 from javiromero/docstrings
Uppercase first word in docstrings. Change to an imperative form.
2016-07-22 10:33:58 -03:00
Javi Romero
1aab6e3bc2 Add changes to changelog. 2016-07-22 12:54:42 +02:00
Javi Romero
7e37497d5a Uppercase first word in docstrings. Change to an imperative form. Add name to authors. 2016-07-22 12:39:06 +02:00
Bruno Oliveira
ae0798522f Merge pull request #1711 from nicoddemus/invocation-scoped-fixtures
Invocation scoped fixtures
2016-07-21 19:48:52 -03:00
Florian Bruhin
832ada1b44 Merge pull request #1747 from nicoddemus/line-match-stringio
Log LineMatcher output in a stream instead of stderr
2016-07-21 09:38:11 +02:00
Bruno Oliveira
4c112401c5 Log LineMatcher output in a stream instead of stderr
This makes the match/nomatch output appear as part
of the fnmatch_lines() error on pytest's output instead
of globbered together with general stdout/stderr capture
2016-07-20 22:35:43 -03:00
Bruno Oliveira
05f3422d7c Make monkeypatch invocation-scoped 2016-07-20 22:05:49 -03:00
Bruno Oliveira
4f2bf965cb Merge remote-tracking branch 'upstream/features' into invocation-scoped-fixtures 2016-07-20 21:16:27 -03:00
Bruno Oliveira
eaa4ee3fdf Merge pull request #1746 from pytest-dev/conftest-exception-printing
Conftest exception printing
2016-07-20 21:03:39 -03:00
Bruno Oliveira
6aea164b6d Add more tests for invocation scoped fixtures 2016-07-20 21:02:36 -03:00
Bruno Oliveira
20f97c3041 Small documentation improvements 2016-07-20 20:22:28 -03:00
Bruno Oliveira
e0f08a73ab Merge branch 'features' into conftest-exception-printing 2016-07-20 19:33:36 -03:00
Bruno Oliveira
93aae987a2 Merge pull request #1744 from RonnyPfannschmidt/existfirst-override
allow --exitfirst/-x to be overridden by a following --maxfail
2016-07-20 18:16:07 -03:00
Bruno Oliveira
1204cbade4 Merge pull request #1745 from RonnyPfannschmidt/skip-compat
skipping plugin: remove python2.5 compat code
2016-07-20 18:14:20 -03:00
Ronny Pfannschmidt
9dadaa8a41 skipping plugin: remove python2.5 compat code 2016-07-20 17:45:20 +02:00
Ronny Pfannschmidt
0403266bf0 record --exitfirst change in changelog 2016-07-20 17:23:07 +02:00
Ronny Pfannschmidt
3fd8257c17 add test for --maxfail=NUM overiding -x 2016-07-20 17:20:10 +02:00
Ronny Pfannschmidt
2a05c311e9 implement exitfirst as store_const option
this makes it possible to override with a later maxfail
2016-07-20 17:15:29 +02:00
Bruno Oliveira
bcc58ec916 Merge pull request #1740 from RonnyPfannschmidt/float-argument
optparse compatibility - add float and complex
2016-07-19 19:17:35 -03:00
Ronny Pfannschmidt
9af872a230 update changelog 2016-07-19 20:11:47 +02:00
Ronny Pfannschmidt
61cc5c4d4e argument parsing: always warn for string types
fix #1741
2016-07-19 10:33:25 +02:00
Ronny Pfannschmidt
317b3f257d optparse compatibility - add float and complex
also documents the implementation quality
fixes #457
2016-07-19 10:20:41 +02:00
Floris Bruynooghe
2b9973846e Merge pull request #1736 from Avira/features
Add backwards compatibility docs
2016-07-18 11:17:48 +02:00
Oliver Bestwalter
58a8150bc5 add backwards compatibility policy 2016-07-17 21:14:16 +02:00
Bruno Oliveira
0ac3eaa1db Merge pull request #1735 from flub/reinterpret-docs
Document the re-writing of plugins
2016-07-17 12:48:33 -03:00
Floris Bruynooghe
0a53797fa3 Document the re-writing of plugins 2016-07-17 12:30:21 +01:00
Ronny Pfannschmidt
8a73a2ad60 Merge pull request #1734 from nicoddemus/issue-1728-inconsistent-setup-teardown
setup_* and teardown_* functions argument now optional
2016-07-15 14:59:22 +02:00
Floris Bruynooghe
fb21493856 Merge pull request #1733 from flub/remove-reinterpret
Remove assertion reinterpretation
2016-07-15 12:46:25 +01:00
Bruno Oliveira
ff8fb4950e setup_* and teardown_* functions argument now optional
setup_module, setup_function and setup_method
extra argument are now optional and may be omitted.

Fix #1728
2016-07-14 23:41:40 -03:00
Floris Bruynooghe
d1852a48b7 Remove assertion reinterpretation
The assertion reinterpretation is an old backwards compatibility
mode which was no longer being maintained on feature-parity with
the assertion rewriting mode.  It was also responsible for some
dubious patching of builtins and test with side-effects would
suddenly start passing.  Since re-writing has been the default for
a long time and plugins are now also re-written it is time to
retire reinterpretation.
2016-07-15 00:33:39 +01:00
Bruno Oliveira
ee374e3b80 Merge pull request #1731 from nicoddemus/improve-test-args-deprecated
Make assert in test_str_args_deprecated more resilient
2016-07-14 19:18:13 -03:00
Bruno Oliveira
3328cd2620 Make assert in test_str_args_deprecated more resilient
This attempts to fix CI which broke because of this test.

Other warnings introduced in the future could break
this test.
2016-07-14 18:37:59 -03:00
Bruno Oliveira
350ebc9167 Merge pull request #1730 from RedBeardCode/pytest-1536
Added confcutdir in testing/test_conftest.py::test_conftest_import_or…
2016-07-14 17:02:58 -03:00
Floris Bruynooghe
24fbbbef1f Merge pull request #1641 from flub/rewrite-plugins
Rewrite plugins
2016-07-14 19:39:15 +01:00
RedBeardCode
22bb43413f Added confcutdir in testing/test_conftest.py::test_conftest_import_order and
testing/python/fixture.py::TestAutouseManagement::()::
  test_class_function_parametrization_finalization to avoid problems with
  abandoned conftest.py files in /tmp dir.
  Fixes #1536
2016-07-14 18:15:38 +02:00
Florian Bruhin
691dc8bc68 Merge pull request #1727 from nicoddemus/deprecate-str-pytest-main
Deprecate support for passing command-line as string to pytest.main()
2016-07-14 14:42:14 +02:00
Florian Bruhin
14af12cb7b Merge pull request #1717 from nicoddemus/nose-yield-tests-docs
Document limitations for yield-tests in nose
2016-07-14 14:40:27 +02:00
Floris Bruynooghe
51ee7f8734 Fixup things after rebase
Some changes to make things work on top of current features branch.
2016-07-14 12:42:29 +01:00
Bruno Oliveira
9007e16cdf Document limitations for yield-tests in nose
Also add nose doc to the root toctree

Closes #1716
2016-07-14 08:20:01 -03:00
Bruno Oliveira
02dd7d612a Remove duplicated changelog entry and formatting fix 2016-07-14 08:16:27 -03:00
Bruno Oliveira
ab0b6faa5f Deprecate support for passing command-line as string to pytest.main()
Fixes #1723
2016-07-14 08:11:43 -03:00
Bruno Oliveira
1fb09d9dd5 Merge pull request #1726 from nicoddemus/warnings-displayed-by-default
Warnings displayed by default
2016-07-13 19:33:49 -03:00
Bruno Oliveira
1266ebec83 Merge remote-tracking branch 'upstream/features' into warnings-displayed-by-default
# Conflicts:
#	CHANGELOG.rst
#	testing/test_terminal.py
2016-07-13 18:45:15 -03:00
Bruno Oliveira
6e9ee2b766 Merge pull request #1724 from blueyed/followup-pr1718-remove-newline
funcarg_prefix_warning: remove newline
2016-07-13 15:46:16 -03:00
Daniel Hahler
3cfebdd7c5 funcarg_prefix_warning: remove newline
Followup to https://github.com/pytest-dev/pytest/pull/1718.
2016-07-13 18:33:24 +02:00
Floris Bruynooghe
743f59afb2 Introduce pytest.register_assert_rewrite()
Plugins can now explicitly mark modules to be re-written.  By default
only the modules containing the plugin entrypoint are re-written.
2016-07-13 17:31:09 +01:00
Floris Bruynooghe
944da5b98a Avoid rewrite warning for inline runs
When running pytest inline/inprocess we plugins have already been
imported and re-writen, so avoid the warning.
2016-07-13 17:29:19 +01:00
Floris Bruynooghe
a98e3cefc5 Enable re-writing of setuptools-installed plugins
Hook up the PEP 302 import hook very early in pytest startup so
that it gets installed before setuptools-installed plugins are
imported.  Also iterate over all installed plugins and mark them
for rewriting.  If an installed plugin is already imported then
a warning is issued, we can not break since that might break
existing plugins and the fallback will still be gracefull to
plain asserts.

Some existing tests are failing in this commit because of the new
warning triggered by inline pytest runs due to the hypothesis
plugin already being imported.  The tests will be fixed in the next
commit.
2016-07-13 17:29:19 +01:00
Bruno Oliveira
dd5ce96cd7 Merge pull request #1718 from blueyed/fix-funcarg_prefix_warning
Add punctuation to funcarg_prefix_warning
2016-07-13 12:53:54 -03:00
Florian Bruhin
aeccd6b4a2 Merge pull request #1720 from nicoddemus/changelog-formatting
Improve overall CHANGELOG formatting and consistency for 3.0
2016-07-13 15:58:38 +02:00
Bruno Oliveira
44c3055e79 Merge pull request #1721 from bronsen/patch-1
Docs: De-404 links in changelog
2016-07-13 10:05:14 -03:00
Bruno Oliveira
4a763accc5 Improve overall CHANGELOG formatting and consistency for 3.0 2016-07-13 08:52:36 -03:00
Kalle Bronsen
dfe1209d2c De-404 links in changelog 2016-07-13 11:41:27 +02:00
Florian Bruhin
54ea27c283 Merge pull request #1719 from nicoddemus/fix-2.10-versions-in-docs
Fix 2.10 -> 3.0 versions in docs
2016-07-13 08:10:13 +02:00
Bruno Oliveira
f827810fa8 Fix 2.10 -> 3.0 versions in docs 2016-07-12 21:02:40 -03:00
Daniel Hahler
15e97a7c78 Add punctuation to funcarg_prefix_warning 2016-07-12 23:49:09 +02:00
Ronny Pfannschmidt
c4f20a1834 Merge pull request #1712 from anntzer/custom-debugger
Allow passing a custom Pdb subclass via --pdbcls.
2016-07-12 16:45:07 +02:00
Ronny Pfannschmidt
4c56c95eb8 Merge pull request #1714 from nicoddemus/deprecate-yield-tests-funcarg-prefix
Deprecate yield tests funcarg prefix
2016-07-12 11:43:59 +02:00
Antony Lee
7ee3dd1cb5 Add tests for custom pdb class.
(and edit CHANGELOG)
2016-07-11 20:07:29 -07:00
Bruno Oliveira
458ecae1df Replace all usages of "pytest_funcarg__" for @pytest.fixture 2016-07-11 22:21:52 -03:00
Bruno Oliveira
ad4125dc0d Deprecate "pytest_funcarg__" prefix to declare fixtures
Fixes #1684
2016-07-11 22:21:50 -03:00
Bruno Oliveira
5506dc700c Deprecate yield tests
Closes #16
Closes #1324
2016-07-11 22:21:49 -03:00
Bruno Oliveira
0dd1c8bf14 Add test to ensure capsys and capfd error out when using "getfixturevalue" inside a test 2016-07-11 20:48:38 -03:00
Bruno Oliveira
0ca06962e9 Improve docs 2016-07-11 20:33:16 -03:00
Bruno Oliveira
2ffe354f21 Add CHANGELOG for invocation-scoped fixtures 2016-07-11 20:32:59 -03:00
Bruno Oliveira
fb4da00a32 Merge remote-tracking branch 'upstream/features' into invocation-scoped-fixtures 2016-07-11 20:09:13 -03:00
Bruno Oliveira
6f68dfcc47 Merge pull request #1710 from RonnyPfannschmidt/fixture-split
Fixture split 2nd attempt
2016-07-10 12:10:07 -03:00
Antony Lee
6383b53ad9 Allow passing a custom Pdb subclass via --pdbcls.
This obviates the need for plugins such as `pytest-ipdb`; instead one
can simply call `py.test --pdb=IPython.core.debugger:Pdb`
2016-07-09 21:10:52 -07:00
Bruno Oliveira
8ed055efd8 Add acceptance test for invocation-scoped fixtures 2016-07-09 22:52:07 -03:00
Bruno Oliveira
775100881a Implement invocation-scoped fixtures 2016-07-09 22:52:05 -03:00
Bruno Oliveira
29289b472f Add documentation for "invocation" scoped fixture 2016-07-09 16:51:25 -03:00
Ronny Pfannschmidt
8c49561470 split most fixture related code into own plugin 2016-07-09 20:36:00 +02:00
Florian Bruhin
7a2058e3db Merge pull request #1709 from The-Compiler/changelog
Clean up changelog
2016-07-08 18:52:28 +02:00
Florian Bruhin
668ebb102c Clean up changelog
- Merged 3.0 and 2.10 as much stuff from the sprint went to the 2.10
  section.
- Cleaned up mixture of link/text blocks
- Moved some entries to "Bug Fixes" and "Incompatible changes"
- Stop doing "Fixes (#123) ..." because it looks weird
- Add some new empty points for all sections
2016-07-08 18:51:26 +02:00
Bruno Oliveira
293351cfd0 Merge pull request #1705 from RonnyPfannschmidt/merge-master
Merge from master to features
2016-07-08 08:15:54 -03:00
Ronny Pfannschmidt
dad6aa8a16 fix duplicate target in changelog 2016-07-06 13:51:13 +02:00
Ronny Pfannschmidt
b9a91dc112 merge from master to features 2016-07-06 11:51:48 +02:00
Bruno Oliveira
f31c31a73c Merge pull request #1695 from sallner/feature-setup-show
Feature setup show
2016-07-05 21:29:01 -03:00
aostr
94e4a2dd67 * implemented changes recommended by nicoddemus 2016-07-05 15:22:27 +02:00
Javier Domingo Cansino
0171cfa30f Fixing link to issue and creating testcase that shows that it finds the line in the stderr lines 2016-07-05 10:39:12 +01:00
Javier Domingo Cansino
61e605f60b Making conftest import failures easier to debug 2016-07-05 10:04:42 +01:00
Ronny Pfannschmidt
cc0920ceb1 Merge pull request #1699 from nicoddemus/404-links-on-talks-docs
Fix links and removed 404 links from talks.rst
2016-07-05 08:44:23 +02:00
Florian Bruhin
067e044f97 Merge pull request #1700 from nicoddemus/split-appveyor
Split AppVeyor test runs in multiple jobs to avoid timeout issues
2016-07-05 06:43:39 +02:00
Bruno Oliveira
10c5e6fd9c Split AppVeyor test runs in multiple jobs to avoid timeout issues
Some of our builds have been timing out (over 1 hour),
on AppVeyor
2016-07-04 21:54:21 -03:00
Bruno Oliveira
8d39ce17da Fix links and removed 404 links from talks.rst
Fix #1696
2016-07-04 21:32:57 -03:00
Steffen Allner
6438895a23 Fix PEP-8. 2016-07-03 22:33:21 +02:00
Steffen Allner
b650c3c118 Implement --setup-show cli flag
to also be able to see fixture setup with normal test execution.
2016-07-03 22:30:51 +02:00
Steffen Allner
f7b5bb2f97 Merged branch features into features 2016-07-03 21:07:02 +02:00
Bruno Oliveira
f74dd8550f Merge pull request #1692 from pytest-dev/changelog
Add changelog to requirements for pytest-dev plugins
2016-06-30 17:39:14 -03:00
Florian Bruhin
e3c43a1462 Add changelog to requirements for pytest-dev plugins
Closes #1691
2016-06-30 22:25:09 +02:00
Florian Bruhin
7927dff8a1 Merge pull request #1678 from RonnyPfannschmidt/drop-python30-32
drop python 3.0-3.2 support code from setup.py
2016-06-30 11:15:49 +02:00
Ronny Pfannschmidt
1451a1ab00 remove unsupported python versions from code/source xfail 2016-06-30 10:03:40 +02:00
Bruno Oliveira
75ecd94294 Merge pull request #1689 from quodlibetor/autouse-docs
Document the interaction of autouse scopes
2016-06-29 18:08:06 -03:00
Brandon W Maister
771c4539fa Document the interaction of autouse scopes
I wouldn't have even attempted what I did to cause #1688 if this had
been there.
2016-06-29 16:52:13 -04:00
Ronny Pfannschmidt
2a43237527 docs: no longer include python 3.0-3.2 in the index page 2016-06-27 18:20:56 +02:00
Ronny Pfannschmidt
7dc8d1ab60 fix typo and remove python3.2 from readme 2016-06-27 18:19:00 +02:00
Florian Bruhin
1e60294188 Merge pull request #1679 from eli-b/patch-1
catched -> caught
2016-06-27 18:02:16 +02:00
Ronny Pfannschmidt
e877e25587 drop python 3.0-3.2 support code from setup.py
addresses #1627
2016-06-27 17:55:37 +02:00
Eli Boyarski
21d27784eb catched -> caught
Even though catch is a Python keyword, 'catched' just looks terrible in text.
If the text was supposed to reference the keyword, then 'catched' should be changed to "'catch'ed".
2016-06-27 15:41:40 +03:00
Bruno Oliveira
ccd395ffe0 Merge pull request #1659 from RonnyPfannschmidt/failtest-586
xfailing test for #568
2016-06-27 07:38:14 -03:00
Ronny Pfannschmidt
76756c0c0b mark tests: use better name of the test for #568 2016-06-27 11:57:21 +02:00
Florian Schulze
bc5a8c761e Fix version in readme. 2016-06-27 11:33:36 +02:00
Florian Schulze
3feee0c483 Prepare 0.1 release. 2016-06-27 11:32:54 +02:00
Florian Schulze
b9c4ecf5a8 Add MANIFEST.in. 2016-06-27 11:32:38 +02:00
Bruno Oliveira
44695ae46c Fix CHANGELOG: obestwalter appearing twice due to mergig separate PRs 2016-06-26 23:44:07 +02:00
Bruno Oliveira
7e78965c79 Merge branch 'logic_brackets' 2016-06-26 21:34:37 +02:00
Bruno Oliveira
58e558141d Remove commented out code 2016-06-26 21:19:07 +02:00
Bruno Oliveira
22c2d87633 Fix bad merge in CHANGELOG 2016-06-26 21:18:01 +02:00
Bruno Oliveira
5891061ac1 Merge pull request #1675 from kvas-it/issue-1562
Add warning for assertions on tuples #1562
2016-06-26 16:09:15 -03:00
Bruno Oliveira
48ac1a0986 Merge branch 'remove-old-entry-points' into features 2016-06-26 20:38:59 +02:00
Bruno Oliveira
db9b3e9522 Merge pull request #1677 from nicoddemus/remove_cmd_options
Remove cmd options
2016-06-26 15:37:59 -03:00
Bruno Oliveira
b9536608c5 Add issue and obestwalter to CHANGELOG
Fix #1632
2016-06-26 20:36:04 +02:00
Bruno Oliveira
f7a2048e96 Merge branch 'features' of https://github.com/Avira/pytest into remove-old-entry-points 2016-06-26 20:32:38 +02:00
Bruno Oliveira
7239f36466 Improve formatting in CHANGELOG 2016-06-26 19:41:01 +02:00
RedBeardCode
1b0dbd8c40 Move the freezing function from genscript.py to a new module freeze_support.py 2016-06-26 19:37:24 +02:00
RedBeardCode
0e2ebc96ff Remove deprecated cmd options
Fixes #1657
2016-06-26 19:26:04 +02:00
aostr
b4e0fabf93 * added missing link to the referenced issue 2016-06-26 06:52:50 +02:00
aostr
1ce4670062 * removed tailing whitespaces 2016-06-26 06:51:57 +02:00
Vasily Kuznetsov
6d4cee2159 Add a test for indirect use of tuple in the assert that should not cause a warning 2016-06-26 02:21:51 +02:00
Vasily Kuznetsov
0db4ae15a9 Update changelog 2016-06-25 19:34:55 +02:00
Vasily Kuznetsov
c17027e576 Warn about asserts on tuples (fixes #1562) 2016-06-25 19:21:48 +02:00
aostr
e04d9ff80b * now showing pytest warnings summary by default.
* added ``--disable-pytest-warnings` flag to let users disable the warnings summary.
* extended/changed unit tests for the changes in the pytest core.
2016-06-25 18:16:13 +02:00
RedBeardCode
e2f550156e Improve of the test output for logical expression with brackets.
Fixes #925
2016-06-25 18:10:36 +02:00
holger krekel
68bed00d5b Merge pull request #1667 from fengxx/feature/override_ini_option
Add --overwrite-ini ININAME=INIVALUE cli option
2016-06-25 18:10:10 +02:00
Ted Xiao
856e6cab75 add --override-ini option to overrides ini values
Signed-off-by: Ted Xiao <xiao.xj@gmail.com>
2016-06-25 23:45:32 +08:00
holger krekel
13a188fe37 Merge pull request #1647 from sallner/features
Add new options to report fixture setup and teardown
2016-06-25 16:38:37 +02:00
Oliver Bestwalter
3a9e9fdf82 rephrase changes in CHANGELOG.rst 2016-06-25 16:04:23 +02:00
Oliver Bestwalter
72450408ed add changes in CHANGELOG.rst 2016-06-25 16:00:49 +02:00
Ronny Pfannschmidt
95b83958f4 add xfailing test for issue #568 2016-06-25 15:49:23 +02:00
Ronny Pfannschmidt
2af3a7a9d7 Merge pull request #1519 from omarkohl/pytest_skip_decorator
Raise CollectError if pytest.skip() is called during collection
2016-06-25 15:20:34 +02:00
Florian Bruhin
35cd12e4de Merge pull request #1660 from hackebrot/parametrize-with-fixtures
Proposal: Parametrize with fixtures
2016-06-25 15:05:27 +02:00
Raphael Pierzina
1b6bc4d606 Add feature proposal to changelog 2016-06-25 14:58:18 +02:00
Bruno Oliveira
c519b9517a Merge pull request #1663 from aostr/master
Rename the default plugin "pdb" into "debugging"
2016-06-25 09:56:54 -03:00
Raphael Pierzina
eb98a8eefb Change version in issues section to pytest 3.0 only 2016-06-25 14:52:57 +02:00
Raphael Pierzina
acfdd85dff Move document to proposals subfolder 2016-06-25 14:42:19 +02:00
Bruno Oliveira
e0242146ec Merge pull request #1666 from pytest-dev/1564-changelog
Add changelog entry for #1564
2016-06-25 09:34:21 -03:00
Bruno Oliveira
df17f862fa Merge pull request #1648 from blueyed/simplify-Argument-__repr__
Simplify Argument.__repr__
2016-06-25 09:26:50 -03:00
Bruno Oliveira
7eb1318db2 Merge pull request #1656 from pytest-dev/rm-indiegogo-links
Update website wrt indiegogo campaign
2016-06-25 09:22:07 -03:00
Florian Bruhin
ce603dc0ea Add changelog entry for #1564 2016-06-25 14:18:41 +02:00
Ronny Pfannschmidt
70ea3ce7f7 Merge pull request #1564 from The-Compiler/issue1479
Don't ignore ImportError when importing setuptools plugins
2016-06-25 14:09:48 +02:00
aostr
9a5224e2f8 Renamed the pdb module and changed unit tests accordingly 2016-06-25 12:37:31 +02:00
Danielle Jenkins
32ca5cdb09 Update changelog for new fixture hooks. 2016-06-25 12:33:31 +02:00
Oliver Bestwalter
891e1677b6 Remove all py.test-X* entry points.
The versioned, suffixed entry points are not documented and a leftover from a pre-virtualenv world. They also are broken for wheels.
2016-06-25 12:27:05 +02:00
Danielle Jenkins
9877bf47e3 Improve commenting for setupplan unittest. 2016-06-25 12:21:31 +02:00
Danielle Jenkins
7a3daac85b Add docs for setuponly and setupplan options. 2016-06-25 12:21:12 +02:00
Danielle Jenkins
da5c579d82 Move setupplan and setuponly options to their respective modules.
Also, changed their group from "general" to "debugconfig".
2016-06-25 12:20:56 +02:00
Danielle Jenkins
032ce8baf6 Switch setuponly and setupplan options to a hook-based implementation. 2016-06-25 12:19:46 +02:00
aostr
05b5554cac Renamed pytest pdb to debugging which conflicts with python pdb.
Combining multiple imports the "import pdb" imports the pytest module
as opposed to the python debugger.
2016-06-25 12:09:05 +02:00
Raphael Pierzina
5860c609ae Remove note on scoping 2016-06-25 11:09:46 +02:00
Raphael Pierzina
526c564576 Fix rst bullet point lists 2016-06-25 11:06:17 +02:00
Raphael Pierzina
693859210a Add yielded values to function example 2016-06-25 11:00:54 +02:00
Raphael Pierzina
4f8b8c8d31 Add alternative approach that uses wrappers 2016-06-25 10:55:08 +02:00
Raphael Pierzina
c6a711c2fc Add proposed solution using a module function 2016-06-25 10:50:14 +02:00
Raphael Pierzina
84f0dcecf8 Add issues section to proposal doc 2016-06-25 10:10:57 +02:00
Florian Bruhin
757f37f445 Don't ignore ImportError with setuptools plugins
This was added in b2d66b9e7b but is a bad
idea. When a plugin can't be imported, commandline options (optionally
set in pytest.ini) could be undefined, which means pytest bails out
much earlier before showing the warning, which is hard to debug.

Fixes #1479, also see #1307 and #1497
2016-06-25 09:56:22 +02:00
Daniel Hahler
939407ef63 Simplify Argument.__repr__
I have came across this when noticing that universal-ctags fails to parse
this correctly (https://github.com/universal-ctags/ctags/issues/997).
2016-06-25 09:31:31 +02:00
Omar Kohl
b3615ac29d Update CHANGELOG with #607 and add version 3.0.0.dev1 2016-06-24 20:56:21 +02:00
Omar Kohl
d81f23009b Raise CollectError if pytest.skip() is called during collection
pytest.skip() must not be used at module level because it can easily be
misunderstood and used as a decorator instead of pytest.mark.skip, causing the
whole module to be skipped instead of just the test being decorated.

This is unexpected for users used to the @unittest.skip decorator and therefore
it is best to bail out with a clean error when it happens.

The pytest equivalent of @unittest.skip is @pytest.mark.skip .

Adapt existing tests that were actually relying on this behaviour and add a
test that explicitly test that collection fails.

fix #607
2016-06-24 20:56:21 +02:00
Bruno Oliveira
0c63762d9c Merge pull request #1654 from tomviner/issue1503/remove_collapse_false
Fixes #1503 no longer collapse false explanations
2016-06-24 12:53:49 -03:00
Brianna Laugher
7612b650a0 update sprint page to be past tense 2016-06-24 17:24:06 +02:00
Brianna Laugher
62255d8000 rm global header 2016-06-24 17:12:41 +02:00
Brianna Laugher
ea5bda0898 remove links to funding campaign 2016-06-24 17:11:29 +02:00
Tom Viner
77689eb486 Fixes #1503 no longer collapse false explanations 2016-06-24 15:35:24 +02:00
Bruno Oliveira
3d263c64c3 Merge pull request #1626 from tomviner/issue1625/rename-getfuncargvalue
issue1625, rename getfuncargvalue to getfixturevalue
2016-06-24 08:58:32 -03:00
Raphael Pierzina
dc55551213 Start proposal for parametrize with fixtures 2016-06-24 12:08:57 +02:00
Tom Viner
df9918eda3 issue1625, name getfuncargvalue to getfixturevalue 2016-06-24 10:08:19 +02:00
Vasily Kuznetsov
c6af737d4e Fix fixture parameter display when ids is a function 2016-06-23 10:54:22 +02:00
Vasily Kuznetsov
1a5e530b98 Fix capturing with --setup-only/--setup-plan 2016-06-23 10:23:04 +02:00
Ronny Pfannschmidt
f2bb3df310 Merge pull request #1645 from userzimmermann/sprint/addoption-check
added check for already existing option names to OptionGroup.addoption()
2016-06-23 07:52:46 +02:00
Florian Bruhin
6359e75ff8 Trivial spelling fix in runtest_setup.py 2016-06-22 20:18:00 +02:00
Stefan Zimmermann
69bab4ab04 added check for already existing option names to OptionGroup.addoption() 2016-06-22 18:01:35 +02:00
Steffen Allner
ecc97aa3b9 Use correct links in changelog. 2016-06-22 17:52:13 +02:00
Steffen Allner
dd97a2e7c8 Merge from upstream 2016-06-22 17:51:48 +02:00
Steffen Allner
0dbf77e08e Add to changelog and authors. 2016-06-22 17:37:58 +02:00
Vasily Kuznetsov
f7d50dfa91 Add a test for handling of dynamic requests for fixtures from other fixtures 2016-06-22 17:24:55 +02:00
Ronny Pfannschmidt
7d60fcc098 Merge pull request #1643 from RonnyPfannschmidt/merge-master
Merge master
2016-06-22 17:05:59 +02:00
Vasily Kuznetsov
c8c32fd9c0 Merge with upstream 2016-06-22 17:00:35 +02:00
Vasily Kuznetsov
61992b4e22 Implement --setup-plan option 2016-06-22 16:45:36 +02:00
Vasily Kuznetsov
f59d8f7720 Fix the tests (#3)
* Fix the tests

* Fix .format string failures on python 2.6
2016-06-22 16:23:58 +02:00
Ronny Pfannschmidt
18ef7de96b merge from master again 2016-06-22 16:03:52 +02:00
Ronny Pfannschmidt
e96cd51a2a Merge remote-tracking branch 'upstream/features' into merge-master 2016-06-22 16:03:00 +02:00
Ronny Pfannschmidt
f7585c7549 Merge pull request #1635 from Avira/master
Add test for change in pull request #1631
2016-06-22 15:49:09 +02:00
Ronny Pfannschmidt
9cb851716d Merge pull request #1644 from KangarooCreativeTeam/patch-1
cache.rst: Fix wrong command used
2016-06-22 15:46:09 +02:00
Ronny Pfannschmidt
a2420ce051 Merge pull request #1640 from Avira/features
Add tests for entry points (#1629 )
2016-06-22 15:41:19 +02:00
HEAD KANGAROO
be1dabd6a9 cache.rst: Fix wrong command used
The "Inspecting Cache content" section was showing --cache-clear command,
  but should actually be using --cache-show command.

  Also; update AUTHORS
2016-06-22 14:04:02 +01:00
Vasily Kuznetsov
5e0d78f4f1 Fix .format string failures on python 2.6 2016-06-22 14:53:37 +02:00
Ronny Pfannschmidt
083f64100d merge master into features 2016-06-22 14:39:33 +02:00
Oliver Bestwalter
db79ed5c4d Add tests to make sure expected entry points exist (#1629) 2016-06-22 14:28:53 +02:00
Bruno Oliveira
fb79fa711b Merge branch 'issue1553/diff-final-newline' of https://github.com/tomviner/pytest 2016-06-22 14:21:30 +02:00
Vasily Kuznetsov
1a75139f72 Fix the tests 2016-06-22 13:25:46 +02:00
Steffen Allner
ee311e1eae Merge pull request #2 from kvas-it/features
Add printing of fixture dependencies
2016-06-22 13:04:23 +02:00
Vasily Kuznetsov
2c5c4f3f78 Add printing of fixture dependencies 2016-06-22 12:54:36 +02:00
Florian Schulze
6b135c83be Initial commit. 2016-06-22 12:21:51 +02:00
Steffen Allner
2c6cfa42fa Disable capturing for setuponly output 2016-06-22 12:14:35 +02:00
Steffen Allner
de9ed5e3f4 Merge pull request #1 from kvas-it/features
Factor setuponly code out of runtestprotocol().
2016-06-22 12:04:45 +02:00
Steffen Allner
92bcc36266 Refactor logging of fixtures 2016-06-22 12:01:51 +02:00
Steffen Allner
7d19f83982 Add test for setuponly option 2016-06-22 12:00:45 +02:00
Oliver Bestwalter
7d87a1b127 Add test for failing assertion
Should contain function name that caused the failure (see pull request #1631).
2016-06-22 11:23:50 +02:00
Vasily Kuznetsov
6874c3a3cc Factor setuponly code out of runtestprotocol(). 2016-06-22 11:09:54 +02:00
Ronny Pfannschmidt
24179dc99f Merge pull request #1639 from tomviner/fix-changelog-links
fix changelog links
2016-06-22 10:49:35 +02:00
Tom Viner
ec25d398a5 fix changelog links 2016-06-22 10:06:14 +02:00
Tom Viner
98adf204b2 issue 1553: Include terminal newlines in diffs 2016-06-22 09:50:15 +02:00
Steffen Allner
499c9551c8 Implement working version of --setuponly 2016-06-22 09:42:45 +02:00
Bruno Oliveira
144dc12e55 Merge pull request #1638 from blueyed/fix-CONTRIBUTING
CONTRIBUTING.rst: spelling fixes
2016-06-22 04:28:15 -03:00
Daniel Hahler
09389d2b20 CONTRIBUTING.rst: spelling fixes
[ci skip]
2016-06-22 09:14:07 +02:00
Bruno Oliveira
c3ee1c17bc Merge pull request #1620 from tomviner/issue460/parameterized-subrequest
Issue 460: Fail on getfuncargvalue(<fixture with params>)
2016-06-21 13:43:06 -03:00
Bruno Oliveira
4350f499b2 Merge branch 'issue1629' of https://github.com/davehunt/pytest into features 2016-06-21 18:37:14 +02:00
Bruno Oliveira
61ede096a3 Merge pull request #1631 from Avira/master
help the user in the rare case this assertion actually fails
2016-06-21 13:17:52 -03:00
Bruno Oliveira
2f9d5c2586 Merge pull request #1623 from blueyed/ignore-hidden-files-in-test_pytest_collect_file
Ignore hidden files (.testmondata) in test_pytest_collect_file
2016-06-21 13:17:20 -03:00
Bruno Oliveira
f05d65dc42 Merge pull request #1622 from nicoddemus/issue-1619-conftest-assert-rewrite
Issue 1619 conftest assert rewrite
2016-06-21 13:15:52 -03:00
Bruno Oliveira
573866bfad Merge remote-tracking branch 'upstream/features' into issue-1619-conftest-assert-rewrite 2016-06-21 18:10:19 +02:00
Bruno Oliveira
2305d3271d Merge pull request #1628 from omarkohl/exit_on_collection_error
Exit pytest on collection error (without executing tests)
2016-06-21 13:03:21 -03:00
Bruno Oliveira
406355fd10 Merge pull request #1624 from blueyed/getexecutable-skip-non-zero-returncode
tests: getexecutable: call `--version` on all Pythons
2016-06-21 12:51:48 -03:00
Dave Hunt
393167b94f Update CHANGELOG and add Oliver Bestwalter to AUTHORS 2016-06-21 16:59:14 +02:00
Dave Hunt
ef9dd14963 Introduce pytest command as recommended entry point
Fixes #1629
2016-06-21 16:16:57 +02:00
Oliver Bestwalter
2b5c2f3ed5 help the user in the rare case this assertion actually fails 2016-06-21 14:57:48 +02:00
Omar Kohl
ede7478dcc Exit pytest on collection error (without executing tests)
Add --continue-on-collection-errors option to restore the previous behaviour:
Execute tests (that were successfully collected) even when collection errors
happen.

Some tests had to be modified e.g. because the return code changed to 2
(EXIT_INTERRUPTED) instead of 1 (EXIT_TESTSFAILED) because an Interrupted
exception is raised on collection error.

Implemented via pair programming with:
    Oleg Pidsadnyi <oleg.pidsadnyi@gmail.com>

closes #1421
2016-06-21 13:32:34 +02:00
Bruno Oliveira
819942e964 Return explicit None from rewrite hook's find_module 2016-06-21 12:28:36 +02:00
Bruno Oliveira
8b0fb47c79 Remove print left by accident 2016-06-21 12:23:12 +02:00
Tom Viner
5854a71ece Issue 460: getfuncargvalue fixture w. params err 2016-06-21 11:29:21 +02:00
Bruno Oliveira
5d8d1db4df Update repository transfer instructions 2016-06-21 09:40:22 +02:00
Floris Bruynooghe
9118c0222f Merge .set_config() into constructor 2016-06-21 09:28:10 +02:00
Daniel Hahler
e53e45b55c tests: getexecutable: call --version on all Pythons
This should prevent errors from pyenv:

    pyenv: python2.6: command not found

    The `python2.6' command exists in these Python versions:
      2.6.9

While the pyenv wrapper explicitly returns 127, I think it is better to
just check for non-zero?!
2016-06-21 08:36:02 +02:00
Bruno Oliveira
e0cb046885 Update AUTHORS and CHANGELOG 2016-06-20 23:16:06 +02:00
Bruno Oliveira
3a81d2e012 conftest files now use assertion rewriting
Fix #1619
2016-06-20 23:13:29 +02:00
Daniel Hahler
e9d7989140 Ignore hidden files (.testmondata) in test_pytest_collect_file
`test_pytest_collect_file` fails if you run the tests using `--testmon`,
because pytest-testmon will put its DB there as `.testmondata`.
2016-06-20 22:30:36 +02:00
Florian Bruhin
54872e94b4 Fix test name typo 2016-06-20 18:44:34 +02:00
Florian Bruhin
4f2db6c08d Merge pull request #1616 from palaviv/pytest.raises-message
Pytest.raises custom error message
2016-06-20 18:43:12 +02:00
Ronny Pfannschmidt
f3aead8e49 Merge pull request #1600 from nicoddemus/issue-1599-disable-cap-fixtures
Add disabled() method to capsys and capfd
2016-06-20 15:55:54 +02:00
palaviv
f8d4cadc3d Added versionchanged directives 2016-06-19 23:56:43 +03:00
palaviv
c29130d400 Updated documentation 2016-06-19 23:34:42 +03:00
palaviv
ca093673fb pytest.raises accept cutom message only when used as context manager 2016-06-19 21:24:47 +03:00
Bruno Oliveira
d81ee9acfb Merge pull request #1597 from taschini/pyargs-fix
Ensure that a module within a namespace package can be found by --pyargs
2016-06-19 14:20:52 -03:00
Bruno Oliveira
72bf11cbe9 Add disabled() method to capsys and capfd
Fix #1599
2016-06-19 19:14:36 +02:00
palaviv
e6ff01ada3 CR fixes 2016-06-16 21:09:15 +03:00
palaviv
8ddbca36c9 Add CHANGLOG entry 2016-06-16 20:21:03 +03:00
palaviv
d21886c005 pytest.raises accpets custom message 2016-06-16 20:15:32 +03:00
Bruno Oliveira
7f8e315285 Merge pull request #1615 from gnprice/deadcode
Cut a dead test helper function
2016-06-16 00:42:01 -03:00
Bruno Oliveira
c5424643f0 Merge pull request #1614 from gnprice/loop
Simplify default pytest_runtestloop
2016-06-16 00:29:03 -03:00
Greg Price
ab8b2e75a3 Simplify default pytest_runtestloop
The inner function and the explanatory comment it makes necessary can
all be removed if we switch to an if/else rather than try/except for
this condition.

Perhaps this bit comes from my fondness for C, but I think I would
find this style clearer and easier to understand even if it weren't
for the Python 2 quirk that makes the other style require us to add an
unnecessary-looking function abstraction.  In any case, given that the
alternative does require that abstraction this is definitely simpler.
2016-06-15 18:27:08 -07:00
Greg Price
2a3cbdf4d1 Cut a dead test helper function
This appears to have been unused since commit
320835d "split out pytest-xdist related reporting to the plugin"
in July 2010.  It's the only caller outside of _pytest/runner.py
of the `call_and_report` helper function there, so cutting it out
makes that more of a pure helper function and makes it slightly
easier to understand the code in _pytest/runner.py .
2016-06-15 18:26:10 -07:00
Bruno Oliveira
308396ae3c Merge pull request #1606 from hackebrot/show-fixtures-per-test
Show fixtures per test
2016-06-14 09:54:18 -03:00
Ronny Pfannschmidt
feeee2803e Merge pull request #1586 from nicoddemus/issue-1461-merge-yield-fixture
Make normal fixtures work with "yield"
2016-06-14 10:31:09 +02:00
taschini
1218392413 Added taschini to AUTHORS and #1597 to CHANGELOG.rst. 2016-06-14 07:16:20 +02:00
taschini
4d9e293b4d Incorporated feedback (#1597).
Fixed problem caused in a test on Windows by file left open by PyPy and not immediately garbage collected.
2016-06-14 07:12:40 +02:00
taschini
e2e6e31711 Ensure that a module within a namespace package can be found by --pyargs. 2016-06-14 07:12:40 +02:00
Raphael Pierzina
adc50ac72f Change format for test function locations 2016-06-12 15:58:32 +01:00
Ronny Pfannschmidt
66e66f61e8 Merge pull request #1605 from guyzmo/issue/1604
Fixed issue shadowing error when missing argument on teardown_method
2016-06-12 12:05:37 +02:00
Guyzmo
accd962c9f Fixed issue shadowing error when missing argument on teardown_method
When the method argument is missing on teardown_method, the traceback is
100% internal to pytest, which with default options get pruned. Then
that traceback is empty, leading to a new exception as a traceback shall
not be empty.

This PR fixes that issue by pushing back the last stack on the
traceback, when the stacktrace is empty after pruning. Then the output
is still pruned, but gives meaningful information with the item where it
failed on the stack.

* fixes issue #1604

Signed-off-by: Guyzmo <guyzmo+github@m0g.net>
2016-06-12 03:45:24 +02:00
Raphael Pierzina
b99aace8a9 Fix py26 by using indices in str.format 2016-06-12 00:52:03 +01:00
Raphael Pierzina
bbc6c18448 Add changelog entry for new cli flag 2016-06-12 00:26:32 +01:00
Raphael Pierzina
7eea168106 Implement show_fixtures_per_test and add cli flag 2016-06-12 00:20:06 +01:00
Raphael Pierzina
b47f155d74 Implement tests for --fixtures-per-test 2016-06-12 00:17:50 +01:00
Ronny Pfannschmidt
577cce2554 Merge pull request #1593 from marscher/fix_cwd_explosion
Fix cwd explosion
2016-06-10 07:24:18 +02:00
Bruno Oliveira
bdc29968b8 Remove dead code and simplify code in call_fixture_func 2016-06-08 21:07:56 -03:00
Bruno Oliveira
ed69424917 Remove most content from yieldfixture as it is now deprecated 2016-06-08 21:07:55 -03:00
Bruno Oliveira
371fbe4388 Update CHANGELOG (yield statements in normal fixtures) 2016-06-08 21:07:53 -03:00
Bruno Oliveira
fe4f23c1bf Update docs in prol of using yield statements 2016-06-08 21:07:52 -03:00
Bruno Oliveira
98acda426f Remove yieldctx variable being passed around 2016-06-08 21:07:50 -03:00
Bruno Oliveira
d712428d33 Fix custom name for yield_fixtures 2016-06-08 21:07:49 -03:00
Bruno Oliveira
366879db27 Make normal fixtures work with "yield" 2016-06-08 21:07:47 -03:00
Bruno Oliveira
92323895c9 Use same python which invoked tox for "doctesting" env
This will work for Travis and AppVeyor because both start tox using Python 3
2016-06-08 21:06:19 -03:00
marscher
09d163aa3a [exception handling] Fix case the current working directory (CWD) gets deleted during testing.
Fixes #1235.
2016-06-08 15:18:23 +02:00
Ronny Pfannschmidt
70fdab4cfa Merge pull request #1584 from mgedmin/patch-1
Docs: config.option is deprecated
2016-06-02 09:27:32 +02:00
Marius Gedminas
3ad5b9de86 Docs: config.option is deprecated
https://pytest.org/latest/writing_plugins.html#_pytest.config.Config says config.option is deprecated and one should use config.getoption() instead.
2016-06-02 09:52:56 +03:00
Ronny Pfannschmidt
9b6dc93496 Merge pull request #1583 from nicoddemus/fix-tox-doctesting
Use same python which invoked tox for "doctesting" env
2016-06-02 08:10:33 +02:00
Bruno Oliveira
2c4b76b754 Use same python which invoked tox for "doctesting" env
This will work for Travis and AppVeyor because both start tox using Python 3
2016-06-01 20:30:26 -03:00
Bruno Oliveira
63ced4d486 List contributors alphabetically in AUTHORS 2016-06-01 20:21:51 -03:00
Bruno Oliveira
97c89e6dc3 Merge branch 'fix-all-skipped-but-none-exist' 2016-06-01 20:20:50 -03:00
Bruno Oliveira
dd9c81ca26 Mention #1580 in the CHANGELOG and add Thomas Grainger to AUTHORS 2016-06-01 19:56:45 -03:00
Thomas Grainger
74862b8f2f Don't mark empty doctest files as skipped, fixes #1578 2016-06-01 19:19:14 +01:00
Florian Bruhin
057007fb52 Merge pull request #1582 from graingert/patch-1
Fix rst-lint CHANGELOG error
2016-06-01 19:25:18 +02:00
Thomas Grainger
2898dffb9e Fix rst-lint CHANGELOG error 2016-06-01 17:43:41 +01:00
Ronny Pfannschmidt
7305adfdba fix another copy&paste error in the announcement list 2016-06-01 08:55:44 +02:00
Ronny Pfannschmidt
fad6266a47 finish up the version bump in __init__ i forgot 2016-06-01 08:18:10 +02:00
Ronny Pfannschmidt
b5bd4d959d merge master to features 2016-06-01 08:13:26 +02:00
Ronny Pfannschmidt
f423f08b45 prepare cangelog for the next bugfix release 2016-06-01 08:04:21 +02:00
Ronny Pfannschmidt
5c8b0fb523 fix minor typos 2016-06-01 08:03:22 +02:00
Bruno Oliveira
8c1be624a6 Merge pull request #1554 from RonnyPfannschmidt/merge-master
Merge master into features
2016-05-24 11:09:33 -03:00
Ronny Pfannschmidt
16794feaf6 Merge branch 'master' into merge-master 2016-05-24 08:15:10 +02:00
Bruno Oliveira
5ab5a11544 Merge pull request #1565 from tomviner/issue1544/ignore-build-dist-dirs
Issue 1544: norecursedirs build & dist dirs
2016-05-23 19:30:20 -03:00
Ronny Pfannschmidt
26b526967e merge from master again 2016-05-23 22:33:00 +02:00
TomV
d6dfb1a393 issue 1544: norecursedirs build & dist dirs 2016-05-23 21:02:29 +01:00
Ronny Pfannschmidt
85393d34b6 Merge pull request #1561 from AbdealiJK/ajk/1558_feature
unittest.UnitTestCase: Allow __test__ for methods
2016-05-19 10:17:28 +02:00
Ronny Pfannschmidt
be7a86270c Merge pull request #1541 from RonnyPfannschmidt/document-1540
Document #1540
2016-05-19 10:15:33 +02:00
AbdealiJK
d4c9fa9f1a unittest.UnitTestCase: Allow __test__ for methods
__test__ needs to be checked for methods of a class too. Earlier,
this was not done, and all methods in a class was assumed to be
a test. This commit adds the appropriate condition to ensure that
if the __test__ is set to False, it does not collect that method.

Fixes https://github.com/pytest-dev/pytest/issues/1558
2016-05-19 08:19:57 +05:30
Ronny Pfannschmidt
ec5e05834f fix typo 2016-05-18 21:35:31 +02:00
Ronny Pfannschmidt
eab762ea99 Merge branch 'master' into merge-master 2016-05-13 19:37:41 +02:00
Ronny Pfannschmidt
c49863aa63 merge next chunk from master and fix changelog linting issue 2016-05-13 19:36:47 +02:00
Ronny Pfannschmidt
01d2ff804b Merge commit '56156bb119194014129ac08c4a2c370f0b893104' into merge-master 2016-05-13 17:55:02 +02:00
Ronny Pfannschmidt
68f658b6cc Merge commit '890c2fa555314a67a8d97a1b8ea4881a14be69c4' into merge-master 2016-05-13 17:52:59 +02:00
Ronny Pfannschmidt
4bde70d060 Merge commit 'ec62a3c9e47c3b5b07aa1656815145ffa2882a09' into merge-master 2016-05-13 17:40:14 +02:00
Ronny Pfannschmidt
98dd2ce75c document reason for #1540 2016-04-28 16:22:31 +02:00
Ronny Pfannschmidt
308e76e19c add xfailing test for #1540 2016-04-28 16:11:30 +02:00
Ronny Pfannschmidt
6cc56b4a1b Merge pull request #1535 from palaviv/parametrize-test-ids-hook
introduce pytest_make_parametrize_id hook
2016-04-27 16:16:16 +02:00
palaviv
9733127951 pytest_make_parametrize_id receive config object 2016-04-26 10:23:57 +03:00
Bruno Oliveira
fdee88f086 Merge pull request #1520 from omarkohl/invalid_test_module_name
Raise CollectError if import test module fails
2016-04-25 21:42:41 -03:00
palaviv
53429ed8b8 Added hook to plugin docs and new CHANGELOG record 2016-04-25 18:03:34 +03:00
palaviv
b9faf78d51 Added test_pytest_make_parametrize_id 2016-04-25 17:48:28 +03:00
palaviv
79927428d1 Added pytest_make_parametrize_id hook 2016-04-25 17:11:47 +03:00
Omar Kohl
56855893ca Raise CollectError if import test module fails
One of the reasons for failing to import the test module is invalid Python
identifiers in the full package path of the test module.

fix #1426
2016-04-23 13:50:48 +02:00
Ronny Pfannschmidt
52babba33e Update sprint 2016 2016-04-23 08:56:28 +02:00
Bruno Oliveira
8552860a9b Merge pull request #1532 from RibeiroAna/features
Update sprint2016.rst :)
2016-04-23 01:05:25 -03:00
Ana Ribeiro
f02f72e651 Update sprint2016.rst 2016-04-23 00:11:44 -03:00
Ronny Pfannschmidt
b220c96bf8 Merge pull request #1526 from The-Compiler/tracebackhide
Filter selectively with __tracebackhide__
2016-04-20 13:07:02 +02:00
Florian Bruhin
aa87395c39 Use py.builtin.callable
This restores compatibility with Python 3.0/3.1
2016-04-20 11:18:47 +02:00
Florian Bruhin
75160547f2 Use a callable __tracebackhide__ for filtering
While this leads to slightly more complicated user code for the common
case (checking if the exception is of a given type) it's easier to
implement and more flexible.
2016-04-20 11:09:27 +02:00
Florian Bruhin
4c552d4ef7 Fix tests for python 2.6 2016-04-20 10:36:13 +02:00
Florian Bruhin
b607f6728f Filter selectively with __tracebackhide__
When __tracebackhide__ gets set to an exception type or list/tuple of
exception types, only those exceptions get filtered, while the full
traceback is shown if another exception (e.g. a bug in a assertion
helper) happens.
2016-04-20 10:25:33 +02:00
Ronny Pfannschmidt
0f7aeafe7c Merge pull request #1486 from roolebo/fix-issue-138
Fix issue #138 - support chained exceptions
2016-04-03 19:21:57 +02:00
Bruno Oliveira
e3bc6faa2b Merge pull request #1470 from ceridwen/features
Escape both bytes and unicode strings for "ids" in Metafunc.parametrize
2016-04-03 13:48:30 -03:00
Bruno Oliveira
909d72b474 Merge pull request #1502 from omarkohl/excinfo_match
Implement ExceptionInfo.match() method
2016-04-03 13:48:12 -03:00
Omar Kohl
0c38aacc33 Add self to AUTHORS 2016-04-03 11:23:30 +02:00
Omar Kohl
c578226d43 Implement ExceptionInfo.match() to match regexp on str(exception)
This implements similar functionality to
unittest.TestCase.assertRegexpMatches()

closes #372
2016-04-03 11:22:44 +02:00
Ceridwen
23a8e2b469 Add .hypothesis to .gitignore and try an older version of Hypothesis for 2.6 2016-04-02 11:47:37 -04:00
Ceridwen
08671fcf4a Fix the changelog and dependencies for tox 2016-04-02 10:52:28 -04:00
Ceridwen
491b30c5d9 Add Hypothesis test for _idval and fix bug it found 2016-04-01 22:45:44 -04:00
Ceridwen
b631fc0bc1 Fix test_escaped_parametrized_names_xml 2016-04-01 21:30:45 -04:00
Ceridwen
9b438d56e8 Fix a test_unicode_idval_python2 (now test_unicode_idval) and associated string handling on Python 3 2016-04-01 12:27:17 -04:00
Roman Bolshakov
89df701ae9 Comment a workaround for #1485. 2016-03-27 13:15:56 +03:00
Bruno Oliveira
fed89ef549 Merge pull request #1474 from palaviv/improve-idmaker-duplicate-names
Improve idmaker name selection in case of duplicate ids in parametrize
2016-03-23 20:38:29 -03:00
palaviv
3ffce6ae4a Added thanks and PR links in changlog 2016-03-23 18:53:50 +02:00
palaviv
c66aedfa65 checking first there are duplciates ids before changing to unique names 2016-03-23 18:47:27 +02:00
palaviv
412042d987 added entry to CHANGELOG 2016-03-23 00:21:24 +02:00
palaviv
b8c15a0215 improved idmaker name selection in case of duplicate ids 2016-03-23 00:20:58 +02:00
Ceridwen
1f46015de5 Merge remote-tracking branch 'upstream/features' into features 2016-03-22 16:22:00 -04:00
Ceridwen
4405dd0ffe Escape both bytes and unicode strings for "ids" in Metafunc.parametrize 2016-03-22 01:31:48 -04:00
Ronny Pfannschmidt
da1045151f Merge pull request #1468 from palaviv/allow-none-as-parametrized-test-id
None in paramtrized test id will use automatically generated id
2016-03-20 20:19:50 +01:00
palaviv
dd384f7f78 Added changlog entries 2016-03-20 19:01:47 +02:00
palaviv
7885e43b78 Merge remote-tracking branch 'upstream/features' into allow-none-as-parametrized-test-id 2016-03-20 18:57:17 +02:00
palaviv
32f44ce2fd updated parametrize documentation 2016-03-20 18:54:48 +02:00
Roman Bolshakov
52bc2f8616 Update authors & changelog 2016-03-20 01:06:53 +03:00
Roman Bolshakov
a736e26734 Merge remote-tracking branch 'pytest-dev/master' into fix-issue-138 2016-03-20 01:04:22 +03:00
Roman Bolshakov
fbc5ba08d9 Fix issue #138 2016-03-20 01:02:17 +03:00
palaviv
4b0237c8ee added test for unique names when recievieng identical ids in parametrize 2016-03-19 21:42:47 +02:00
palaviv
877ca5a0bf added test for None in paramtrized ids list 2016-03-19 21:38:24 +02:00
palaviv
a8cfd54871 added test for None in idmaker 2016-03-19 21:23:49 +02:00
palaviv
be1954afbc allow None to be passed in ids list for specific test and recieve idmaker name for test 2016-03-19 21:22:49 +02:00
Bruno Oliveira
2cfcf12d09 Merge pull request #1466 from nicoddemus/merge-master-into-features
Merge master into features after 2.9.1 release
2016-03-18 23:45:14 -03:00
Bruno Oliveira
5fcce8a7d6 Merge branch 'master' into merge-master-into-features 2016-03-18 18:26:56 -03:00
Bruno Oliveira
ceacc12b52 Merge pull request #1454 from tareqalayan/add-global-properties-node
junitxml: add properties node in testsuite level
2016-03-16 18:21:51 -03:00
Tareq Alayan
fa6acdcfd4 junitxml: add properties node in testsuite level
The commit allow users to add a properties node in testsuite level see
example below:

<testsuite errors="0" failures="0" name="pytest" skips="1" tests="1"
time="11.824">
  <properties>
    <property name="ARCH" value="PPC"/>
    <property name="OS" value="RHEL 7.2"/>
    <property name="TestPlanURL" value="https://url.."/>
    <property name="Automated" value="True"/>
  </properties>
  <testcase classname="git.....>
  </testcase>
</testsuite>

The current situation is that properties node can be added to every
testcase node. However, sometimes we need some global properties that
applies to all testcases and give better description for the testsuite
itself.
2016-03-16 13:24:33 +02:00
Ronny Pfannschmidt
5fd82078ad Merge pull request #1441 from kalekundert/features
Add a convenience function for floating-point comparisons
2016-03-15 07:45:07 +01:00
Kale Kundert
5ceee08590 Fix CHANGELOG merge conflicts. 2016-03-14 11:55:50 -07:00
Kale Kundert
0dcc862a56 Fix some typos in the documentation. 2016-03-14 11:38:00 -07:00
Kale Kundert
9e7206a1cf Fix a few stylistic issues. 2016-03-14 11:29:45 -07:00
Ronny Pfannschmidt
0cacdef6c5 Merge pull request #1444 from novas0x2a/fixture-custom-name
Allow custom fixture names for fixtures
2016-03-14 14:08:02 +01:00
Kale Kundert
861265411f Add "thanks" line to the CHANGELOG. 2016-03-12 22:15:19 -08:00
Kale Kundert
916c0a8b36 Fix Decimal() and __ne__() errors. 2016-03-11 16:29:18 -08:00
Kale Kundert
078448008c Discuss alternative float comparison algorithms. 2016-03-11 15:59:48 -08:00
Kale Kundert
42a7e0488d Properly handle inf, nan, and built-in numeric types.
This commit also:

- Dramatically increases the number of unit tests , mostly by borrowing
  from the standard  library's unit tests for math.isclose().

- Refactors approx() into two classes, one of which handles comparing
  individual numbers (ApproxNonIterable) and another which uses the
  first to compare individual numbers or sequences of numbers.
2016-03-11 08:49:26 -08:00
Mike Lundy
9577120592 Allow custom fixture names for fixtures
When defining a fixture in the same module as where it is used, the
function argument shadows the fixture name, which a) annoys pylint and
b) can lead to bugs where you forget to request a fixture into a test
method.

This allows one to define fixtures with a different name than the name
of the function, bypassing that problem.
2016-03-09 14:58:54 -08:00
Kale Kundert
7d155bd3cf Fix sys.version_info errors. 2016-03-08 10:12:31 -08:00
Kale Kundert
6a902924f8 Fix trailing whitespace errors. 2016-03-07 19:56:23 -08:00
Kale Kundert
c9c73b8d8e Fix zero-length field name error in python2.6 2016-03-07 19:54:43 -08:00
Kale Kundert
4d0f066db7 Add approx() to the CHANGELOG. 2016-03-07 18:29:22 -08:00
Kale Kundert
5dab0954a0 Add approx() to the Sphinx docs. 2016-03-07 18:14:49 -08:00
Kale Kundert
b8a8382c2c Reduce the default absolute error threshold to 1e-12. 2016-03-07 16:43:53 -08:00
Kale Kundert
bf97d5b817 Use the plus/minus unicode symbol in the repr string.
This was a challenge because it had to work in python2 and python3,
which have almost opposite unicode models, and I couldn't use the six
library.  I'm also not sure the solution I found would work in python3
before python3.3, because I use the u'' string prefix which I think was
initially not part of python3.
2016-03-07 16:40:41 -08:00
Kale Kundert
dd28e28b34 Make a few stylistic improvements. 2016-03-07 10:10:54 -08:00
Kale Kundert
6f5e1e386a Add a convenient and correct way to compare floats. 2016-03-07 10:10:54 -08:00
Bruno Oliveira
c2b9196a7c Merge remote-tracking branch 'upstream/master' into features 2016-03-02 23:41:56 -03:00
Bruno Oliveira
4a76b2e9b6 Merge branch 'doctest_namespace_inject' into features 2016-03-02 23:38:51 -03:00
Bruno Oliveira
28937a5cd9 Add versionadded directive to doctest_namespace section 2016-03-02 23:37:51 -03:00
Bruno Oliveira
2e02a1c370 Give proper credit for PR #1428 2016-03-02 23:30:42 -03:00
Matt Williams
6dd2ff5332 Correct indentation in documentation 2016-03-02 13:02:15 +00:00
Matt Williams
891e029518 Add a new doctest_namespace fixture
This fixture can be used to inject names into the namespace in which
your doctests run.
2016-03-02 12:43:57 +00:00
Bruno Oliveira
5a2500800d Add 2.10.0.dev1 to CHANGELOG 2016-03-01 18:54:08 -03:00
Bruno Oliveira
c8c5a416ef Bump version to 2.10.0.dev1 2016-03-01 18:48:13 -03:00
240 changed files with 14469 additions and 6852 deletions

View File

@@ -4,5 +4,5 @@ Here's a quick checklist in what to include:
- [ ] Include a detailed description of the bug or suggestion
- [ ] `pip list` of the virtual environment you are using
- [ ] py.test and operating system versions
- [ ] pytest and operating system versions
- [ ] Minimal example if possible

View File

@@ -2,7 +2,14 @@ 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`
- [ ] Make sure to include one or more tests for your change
- [ ] Add yourself to `AUTHORS`
- [ ] Add a new entry to the `CHANGELOG` (choose any open position to avoid merge conflicts with other PRs)
- [ ] Add a new news fragment into the changelog folder
* name it `$issue_id.$type` for example (588.bug)
* if you don't have an issue_id change it to the pr id after creating the pr
* ensure type is one of `removal`, `feature`, `bugfix`, `vendor`, `doc` or `trivial`
* Make sure to use full sentences with correct case and punctuation, for example: "Fix issue with non-ascii contents in doctest text files."
- [ ] Target: for `bugfix`, `vendor`, `doc` or `trivial` fixes, target `master`; for removals or features target `features`;
- [ ] Make sure to include reasonable tests for your change if necessary
Unless your change is a trivial or a documentation fix (e.g., a typo or reword of a small section) please:
- [ ] Add yourself to `AUTHORS`;

4
.gitignore vendored
View File

@@ -18,6 +18,9 @@ include/
*~
.hypothesis/
# autogenerated
_pytest/_version.py
# setuptools
.eggs/
doc/*/_build
@@ -33,3 +36,4 @@ env/
.coverage
.ropeproject
.idea
.hypothesis

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=py27-cxfreeze
- 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'
- env: TOXENV=py37
python: 'nightly'
allow_failures:
- env: TOXENV=py37
python: 'nightly'
script: tox --recreate
notifications:
irc:

94
AUTHORS
View File

@@ -3,89 +3,165 @@ merlinux GmbH, Germany, office at merlinux eu
Contributors include::
Abdeali JK
Abhijeet Kasurde
Ahn Ki-Wook
Alexander Johnson
Alexei Kozlenok
Anatoly Bubenkoff
Andreas Zeidler
Andrzej Ostrowski
Andy Freeland
Anthon van der Neut
Anthony Sottile
Antony Lee
Armin Rigo
Aron Curzon
Aviv Palivoda
Barney Gale
Ben Webb
Benjamin Peterson
Bernard Pratz
Bob Ippolito
Brian Dorsey
Brian Okken
Brianna Laugher
Bruno Oliveira
Cal Leeming
Carl Friedrich Bolz
Charles Cloud
Charnjit SiNGH (CCSJ)
Chris Lamb
Christian Boelsen
Christian Theunert
Christian Tismer
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
Dmitry Pribysh
Duncan Betts
Edison Gustavo Muenz
Edoardo Batini
Eduardo Schettino
Endre Galaczi
Eli Boyarski
Elizaveta Shashkova
Endre Galaczi
Eric Hunsberger
Eric Siegerman
Erik M. Bray
Feng Ma
Florian Bruhin
Floris Bruynooghe
Gabriel Reis
Georgy Dyuldin
Graham Horler
Greg Price
Grig Gheorghiu
Grigorii Eremeev (budulianin)
Guido Wesdorp
Harald Armin Massa
Hui Wang (coldnight)
Ian Bicking
Jaap Broekhuizen
Jan Balster
Janne Vanhala
Jason R. Coombs
Javier Domingo Cansino
Javier Romero
Jeff Widman
John Towler
Jon Sonesen
Jonas Obrist
Jordan Guymon
Joshua Bronson
Jurko Gospodnetić
Justyna Janczyszyn
Kale Kundert
Katarzyna Jachim
Kevin Cox
Kodi B. Arfer
Lee Kamentsky
Lev Maximov
Loic Esteve
Lukas Bednar
Luke Murphy
Maciek Fijalkowski
Maho
Mandeep Bhutani
Manuel Krebber
Marc Schlaich
Marcin Bachry
Mark Abramowitz
Markus Unterwaditzer
Martijn Faassen
Martin K. Scherer
Martin Prusse
Mathieu Clabaut
Matt Bachmann
Matt Duck
Matt Williams
Matthias Hafner
mbyt
Michael Aquilina
Michael Birtwell
Michael Droettboom
Michael Seifert
Michal Wajszczuk
Mike Lundy
Ned Batchelder
Neven Mundar
Nicolas Delaby
Oleg Pidsadnyi
Oliver Bestwalter
Omar Kohl
Omer Hadari
Patrick Hayes
Paweł Adamczak
Pieter Mulder
Piotr Banaszkiewicz
Punyashloka Biswal
Quentin Pradet
Ralf Schmitt
Ran Benita
Raphael Pierzina
Raquel Alegre
Ravi Chandra
Roberto Polli
Romain Dorgueil
Roman Bolshakov
Ronny Pfannschmidt
Ross Lawley
Russel Winder
Ryan Wooden
Samuele Pedroni
Segev Finer
Simon Gomizelj
Skylar Downes
Stefan Farmbauer
Stefan Zimmermann
Stefano Taschini
Steffen Allner
Stephan Obermann
Tareq Alayan
Ted Xiao
Thomas Grainger
Tom Viner
Trevor Bekolay
Tyler Goodlet
Vasily Kuznetsov
Victor Uriarte
Vidar T. Fauske
Vitaly Lashmanov
Vlad Dragos
Wouter van Ackooy
David Díaz-Barquero
Eric Hunsberger
Simon Gomizelj
Russel Winder
Ben Webb
Alexei Kozlenok
Cal Leeming
Feng Ma
Xuecong Liao

File diff suppressed because it is too large Load Diff

View File

@@ -48,7 +48,7 @@ to fix the bug yet.
Fix bugs
--------
Look through the GitHub issues for bugs. Here is sample filter you can use:
Look through the GitHub issues for bugs. Here is a filter you can use:
https://github.com/pytest-dev/pytest/labels/bug
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
@@ -60,8 +60,7 @@ Don't forget to check the issue trackers of your favourite plugins, too!
Implement features
------------------
Look through the GitHub issues for enhancements. Here is sample filter you
can use:
Look through the GitHub issues for enhancements. Here is a filter you can use:
https://github.com/pytest-dev/pytest/labels/enhancement
:ref:`Talk <contact>` to developers to find out how you can implement specific
@@ -70,17 +69,26 @@ features.
Write documentation
-------------------
pytest could always use more documentation. What exactly is needed?
Pytest could always use more documentation. What exactly is needed?
* More complementary documentation. Have you perhaps found something unclear?
* Documentation translations. We currently have only English.
* Docstrings. There can never be too many of them.
* Blog posts, articles and such -- they're all very appreciated.
You can also edit documentation files directly in the Github web interface
without needing to make a fork and local copy. This can be convenient for
small fixes.
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:
@@ -95,13 +103,14 @@ in repositories living under the ``pytest-dev`` organisations:
- `pytest-dev on Bitbucket <https://bitbucket.org/pytest-dev>`_
All pytest-dev Contributors team members have write access to all contained
repositories. pytest core and plugins are generally developed
repositories. Pytest core and plugins are generally developed
using `pull requests`_ to respective repositories.
The objectives of the ``pytest-dev`` organisation are:
* Having a central location for popular pytest plugins
* Sharing some of the maintenance responsibility (in case a maintainer no longer whishes to maintain a plugin)
* Sharing some of the maintenance responsibility (in case a maintainer no
longer wishes to maintain a plugin)
You can submit your plugin by subscribing to the `pytest-dev mail list
<https://mail.python.org/mailman/listinfo/pytest-dev>`_ and writing a
@@ -121,33 +130,26 @@ the following:
- an issue tracker for bug reports and enhancement requests.
- a `changelog <http://keepachangelog.com/>`_
If no contributor strongly objects and two agree, the repository can then be
transferred to the ``pytest-dev`` organisation.
Here's a rundown of how a repository transfer usually proceeds
(using a repository named ``joedoe/pytest-xyz`` as example):
* One of the ``pytest-dev`` administrators creates:
- ``pytest-xyz-admin`` team, with full administration rights to
``pytest-dev/pytest-xyz``.
- ``pytest-xyz-developers`` team, with write access to
``pytest-dev/pytest-xyz``.
* ``joedoe`` is invited to the ``pytest-xyz-admin`` team;
* After accepting the invitation, ``joedoe`` transfers the repository from its
original location to ``pytest-dev/pytest-xyz`` (A nice feature is that GitHub handles URL redirection from
the old to the new location automatically).
* ``joedoe`` is free to add any other collaborators to the
``pytest-xyz-admin`` or ``pytest-xyz-developers`` team as desired.
* ``joedoe`` transfers repository ownership to ``pytest-dev`` administrator ``calvin``.
* ``calvin`` creates ``pytest-xyz-admin`` and ``pytest-xyz-developers`` teams, inviting ``joedoe`` to both as **maintainer**.
* ``calvin`` transfers repository to ``pytest-dev`` and configures team access:
- ``pytest-xyz-admin`` **admin** access;
- ``pytest-xyz-developers`` **write** access;
The ``pytest-dev/Contributors`` team has write access to all projects, and
every project administrator is in it. We recommend that each plugin has at least three
people who have the right to release to PyPI.
Repository owners can be assured that no ``pytest-dev`` administrator will ever make
Repository owners can rest assured that no ``pytest-dev`` administrator will ever make
releases of your repository or take ownership in any way, except in rare cases
where someone becomes unresponsive after months of contact attempts.
As stated, the objective is to share maintenance and avoid "plugin-abandon".
@@ -159,15 +161,11 @@ As stated, the objective is to share maintenance and avoid "plugin-abandon".
Preparing Pull Requests on GitHub
---------------------------------
There's an excellent tutorial on how Pull Requests work in the
`GitHub Help Center <https://help.github.com/articles/using-pull-requests/>`_
.. note::
What is a "pull request"? It informs project's core developers about the
changes you want to review and merge. Pull requests are stored on
`GitHub servers <https://github.com/pytest-dev/pytest/pulls>`_.
Once you send pull request, we can discuss it's potential modifications and
Once you send a pull request, we can discuss its potential modifications and
even add more commits to it later on.
There's an excellent tutorial on how Pull Requests work in the
@@ -208,38 +206,35 @@ but here is a simple overview:
#. Run all the tests
You need to have Python 2.7 and 3.5 available in your system. Now
You need to have Python 2.7 and 3.6 available in your system. Now
running tests is as simple as issuing this command::
$ python runtox.py -e linting,py27,py35
$ tox -e linting,py27,py36
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.
This command will run tests via the "tox" tool against Python 2.7 and 3.6
and also perform "lint" coding-style checks.
#. You can now edit your local working copy.
You can now make the changes you want and run the tests again as necessary.
To run tests on py27 and pass options to pytest (e.g. enter pdb on failure)
to pytest you can do::
To run tests on Python 2.7 and pass options to pytest (e.g. enter pdb on
failure) to pytest you can do::
$ python runtox.py -e py27 -- --pdb
$ tox -e py27 -- --pdb
or to only run tests in a particular test module on py35::
Or to only run tests in a particular test module on Python 3.6::
$ python runtox.py -e py35 -- testing/test_config.py
$ tox -e py36 -- testing/test_config.py
#. Commit and push once your tests pass and you are happy with your change(s)::
$ git commit -a -m "<commit message>"
$ git push -u
Make sure you add a CHANGELOG message, and add yourself to AUTHORS. If you
are unsure about either of these steps, submit your pull request and we'll
help you fix it up.
Make sure you add a message to ``CHANGELOG.rst`` and add yourself to
``AUTHORS``. If you are unsure about either of these steps, submit your
pull request and we'll help you fix it up.
#. Finally, submit a pull request through the GitHub website using this data::
@@ -248,6 +243,6 @@ but here is a simple overview:
base-fork: pytest-dev/pytest
base: master # if it's a bugfix
base: feature # if it's a feature
base: features # if it's a feature

View File

@@ -1,92 +1,61 @@
How to release pytest
--------------------------------------------
Note: this assumes you have already registered on pypi.
.. important::
0. create the branch release-VERSION
use features as base for minor/major releases
and master as base for bugfix releases
pytest releases must be prepared on **Linux** because the docs and examples expect
to be executed in that platform.
1. Bump version numbers in _pytest/__init__.py (setup.py reads it)
#. Install development dependencies in a virtual environment with::
2. Check and finalize CHANGELOG
pip3 install -r tasks/requirements.txt
3. Write doc/en/announce/release-VERSION.txt and include
it in doc/en/announce/index.txt::
#. Create a branch ``release-X.Y.Z`` with the version for the release.
git log 2.8.2..HEAD --format='%aN' | sort -u # lists the names of authors involved
* **patch releases**: from the latest ``master``;
4. Use devpi for uploading a release tarball to a staging area::
* **minor releases**: from the latest ``features``; then merge with the latest ``master``;
devpi use https://devpi.net/USER/dev
devpi upload --formats sdist,bdist_wheel
Ensure your are in a clean work tree.
5. Run from multiple machines::
#. Generate docs, changelog, announcements and upload a package to
your ``devpi`` staging server::
devpi use https://devpi.net/USER/dev
devpi test pytest==VERSION
invoke generate.pre_release <VERSION> <DEVPI USER> --password <DEVPI PASSWORD>
6. Check that tests pass for relevant combinations with::
If ``--password`` is not given, it is assumed the user is already logged in ``devpi``.
If you don't have an account, please ask for one.
#. Open a PR for this branch targeting ``master``.
#. Test the package
* **Manual method**
Run from multiple machines::
devpi use https://devpi.net/USER/dev
devpi test pytest==VERSION
Check that tests pass for relevant combinations with::
devpi list pytest
or look at failures with "devpi list -f pytest".
* **CI servers**
7. Regenerate the docs examples using tox, and check for regressions::
Configure a repository as per-instructions on
devpi-cloud-test_ to test the package on Travis_ and AppVeyor_.
All test environments should pass.
tox -e regen
git diff
#. Publish to PyPI::
invoke generate.publish_release <VERSION> <DEVPI USER> <PYPI_NAME>
8. Build the docs, you need a virtualenv with py and sphinx
installed::
where PYPI_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>`_.
cd doc/en
make html
#. After a minor/major release, merge ``features`` into ``master`` and push (or open a PR).
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::
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>`_.
12. Send release announcement to mailing lists:
- pytest-dev
- testing-in-python
- python-announce-list@python.org
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
.. _devpi-cloud-test: https://github.com/obestwalter/devpi-cloud-test
.. _AppVeyor: https://www.appveyor.com/
.. _Travis: https://travis-ci.org

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

@@ -1,34 +1,39 @@
include CHANGELOG.rst
include LICENSE
include AUTHORS
include pyproject.toml
include README.rst
include CONTRIBUTING.rst
include HOWTORELEASE.rst
include tox.ini
include setup.py
include .coveragerc
recursive-include changelog *
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
graft tasks
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

@@ -1,83 +1,90 @@
.. image:: http://pytest.org/latest/_static/pytest1.png
:target: http://pytest.org
.. image:: http://docs.pytest.org/en/latest/_static/pytest1.png
:target: http://docs.pytest.org
:align: center
:alt: pytest
------
.. image:: https://img.shields.io/pypi/v/pytest.svg
:target: https://pypi.python.org/pypi/pytest
:target: https://pypi.python.org/pypi/pytest
.. image:: https://anaconda.org/conda-forge/pytest/badges/version.svg
:target: https://anaconda.org/conda-forge/pytest
.. image:: https://img.shields.io/pypi/pyversions/pytest.svg
:target: https://pypi.python.org/pypi/pytest
:target: https://pypi.python.org/pypi/pytest
.. image:: https://img.shields.io/coveralls/pytest-dev/pytest/master.svg
:target: https://coveralls.io/r/pytest-dev/pytest
:target: https://coveralls.io/r/pytest-dev/pytest
.. image:: https://travis-ci.org/pytest-dev/pytest.svg?branch=master
:target: https://travis-ci.org/pytest-dev/pytest
.. image:: https://ci.appveyor.com/api/projects/status/mrgbjaua7t33pg6b?svg=true
:target: https://ci.appveyor.com/project/pytestbot/pytest
The ``pytest`` framework makes it easy to write small tests, yet
scales to support complex functional testing for applications and libraries.
scales to support complex functional testing for applications and libraries.
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::
$ py.test
======= test session starts ========
platform linux -- Python 3.4.3, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
$ pytest
============================= 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 ``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.
Due to ``py.test``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://pytest.org/latest/getting-started.html#our-first-test-run>`_ for more examples.
Features
--------
- Detailed info on failing `assert statements <http://pytest.org/latest/assert.html>`_ (no need to remember ``self.assert*`` names);
- Detailed info on failing `assert statements <http://docs.pytest.org/en/latest/assert.html>`_ (no need to remember ``self.assert*`` names);
- `Auto-discovery
<http://pytest.org/latest/goodpractices.html#python-test-discovery>`_
<http://docs.pytest.org/en/latest/goodpractices.html#python-test-discovery>`_
of test modules and functions;
- `Modular fixtures <http://pytest.org/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://pytest.org/latest/unittest.html>`_ (or trial),
`nose <http://pytest.org/latest/nose.html>`_ test suites out of the box;
- Can run `unittest <http://docs.pytest.org/en/latest/unittest.html>`_ (or trial),
`nose <http://docs.pytest.org/en/latest/nose.html>`_ test suites out of the box;
- Python2.6+, Python3.2+, PyPy-2.3, Jython-2.5 (untested);
- Python2.6+, Python3.3+, PyPy-2.3, Jython-2.5 (untested);
- Rich plugin architecture, with over 150+ `external plugins <http://pytest.org/latest/plugins.html#installing-external-plugins-searching>`_ and thriving community;
- Rich plugin architecture, with over 150+ `external plugins <http://docs.pytest.org/en/latest/plugins.html#installing-external-plugins-searching>`_ and thriving community;
Documentation
-------------
For full documentation, including installation, tutorials and PDF documents, please see http://pytest.org.
For full documentation, including installation, tutorials and PDF documents, please see http://docs.pytest.org.
Bugs/Requests
@@ -89,7 +96,7 @@ Please use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issue
Changelog
---------
Consult the `Changelog <http://pytest.org/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,8 @@
#
__version__ = '2.9.2'
__all__ = ['__version__']
try:
from ._version import version as __version__
except ImportError:
# broken installation, we don't even try
# unknown only works because we do poor mans version compare
__version__ = 'unknown'

View File

@@ -57,7 +57,7 @@ If things do not work right away:
which should throw a KeyError: 'COMPLINE' (which is properly set by the
global argcomplete script).
"""
from __future__ import absolute_import, division, print_function
import sys
import os
from glob import glob
@@ -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,12 +1,10 @@
""" python inspection/code generation API """
from __future__ import absolute_import, division, print_function
from .code import Code # noqa
from .code import ExceptionInfo # noqa
from .code import Frame # noqa
from .code import Traceback # noqa
from .code import getrawcode # noqa
from .code import patch_builtins # noqa
from .code import unpatch_builtins # noqa
from .source import Source # noqa
from .source import compile_ as compile # noqa
from .source import getfslineno # noqa

View File

@@ -2,6 +2,7 @@
# CHANGES:
# - some_str is replaced, trying to create unicode strings
#
from __future__ import absolute_import, division, print_function
import types
def format_exception_only(etype, value):

View File

@@ -1,17 +1,21 @@
from __future__ import absolute_import, division, print_function
import sys
from inspect import CO_VARARGS, CO_VARKEYWORDS
import re
from weakref import ref
from _pytest.compat import _PY2, _PY3, PY35, safe_str
import py
builtin_repr = repr
reprlib = py.builtin._tryimport('repr', 'reprlib')
if sys.version_info[0] >= 3:
if _PY3:
from traceback import format_exception_only
else:
from ._py2traceback import format_exception_only
class Code(object):
""" wrapper around Python code objects """
def __init__(self, rawcode):
@@ -28,6 +32,8 @@ class Code(object):
def __eq__(self, other):
return self.raw == other.raw
__hash__ = None
def __ne__(self, other):
return not self == other
@@ -35,12 +41,16 @@ class Code(object):
def path(self):
""" return a path object pointing to source code (note that it
might not point to an actually existing file). """
p = py.path.local(self.raw.co_filename)
# maybe don't try this checking
if not p.check():
try:
p = py.path.local(self.raw.co_filename)
# maybe don't try this checking
if not p.check():
raise OSError("py.path check failed.")
except OSError:
# XXX maybe try harder like the weird logic
# in the standard lib [linecache.updatecache] does?
p = self.raw.co_filename
return p
@property
@@ -139,7 +149,8 @@ class TracebackEntry(object):
_repr_style = None
exprinfo = None
def __init__(self, rawentry):
def __init__(self, rawentry, excinfo=None):
self._excinfo = excinfo
self._rawentry = rawentry
self.lineno = rawentry.tb_lineno - 1
@@ -174,18 +185,6 @@ class TracebackEntry(object):
return self.frame.f_locals
locals = property(getlocals, None, None, "locals of underlaying frame")
def reinterpret(self):
"""Reinterpret the failing statement and returns a detailed information
about what operations are performed."""
from _pytest.assertion.reinterpret import reinterpret
if self.exprinfo is None:
source = py.builtin._totext(self.statement).strip()
x = reinterpret(source, self.frame, should_fail=True)
if not py.builtin._istext(x):
raise TypeError("interpret returned non-string %r" % (x,))
self.exprinfo = x
return self.exprinfo
def getfirstlinesource(self):
# on Jython this firstlineno can be -1 apparently
return max(self.frame.code.firstlineno, 0)
@@ -220,16 +219,24 @@ class TracebackEntry(object):
""" return True if the current frame has a var __tracebackhide__
resolving to True
If __tracebackhide__ is a callable, it gets called with the
ExceptionInfo instance and can decide whether to hide the traceback.
mostly for internal use
"""
try:
return self.frame.f_locals['__tracebackhide__']
tbh = self.frame.f_locals['__tracebackhide__']
except KeyError:
try:
return self.frame.f_globals['__tracebackhide__']
tbh = self.frame.f_globals['__tracebackhide__']
except KeyError:
return False
if py.builtin.callable(tbh):
return tbh(None if self._excinfo is None else self._excinfo())
else:
return tbh
def __str__(self):
try:
fn = str(self.path)
@@ -253,12 +260,13 @@ class Traceback(list):
access to Traceback entries.
"""
Entry = TracebackEntry
def __init__(self, tb):
""" initialize from given python traceback object. """
def __init__(self, tb, excinfo=None):
""" initialize from given python traceback object and ExceptionInfo """
self._excinfo = excinfo
if hasattr(tb, 'tb_next'):
def f(cur):
while cur is not None:
yield self.Entry(cur)
yield self.Entry(cur, excinfo=excinfo)
cur = cur.tb_next
list.__init__(self, f(tb))
else:
@@ -282,7 +290,7 @@ class Traceback(list):
not codepath.relto(excludepath)) and
(lineno is None or x.lineno == lineno) and
(firstlineno is None or x.frame.code.firstlineno == firstlineno)):
return Traceback(x._rawentry)
return Traceback(x._rawentry, self._excinfo)
return self
def __getitem__(self, key):
@@ -301,7 +309,7 @@ class Traceback(list):
by default this removes all the TracebackEntries which are hidden
(see ishidden() above)
"""
return Traceback(filter(fn, self))
return Traceback(filter(fn, self), self._excinfo)
def getcrashentry(self):
""" return last non-hidden traceback entry that lead
@@ -337,6 +345,7 @@ class Traceback(list):
l.append(entry.frame.f_locals)
return None
co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
'?', 'eval')
@@ -345,6 +354,8 @@ class ExceptionInfo(object):
help for navigating the traceback.
"""
_striptext = ''
_assert_start_repr = "AssertionError(u\'assert " if _PY2 else "AssertionError(\'assert "
def __init__(self, tup=None, exprinfo=None):
import _pytest._code
if tup is None:
@@ -352,8 +363,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
@@ -365,7 +376,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)
self.traceback = _pytest._code.Traceback(self.tb, excinfo=ref(self))
def __repr__(self):
return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
@@ -427,6 +438,19 @@ class ExceptionInfo(object):
loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
return unicode(loc)
def match(self, regexp):
"""
Match the regular expression 'regexp' on the string representation of
the exception. If it matches then True is returned (so that it is
possible to write 'assert excinfo.match()'). If it doesn't match an
AssertionError is raised.
"""
__tracebackhide__ = True
if not re.search(regexp, str(self.value)):
assert 0, "Pattern '{0!s}' not found in '{1!s}'".format(
regexp, self.value)
return True
class FormattedExcinfo(object):
""" presenting information about failing Functions and Generators. """
@@ -578,30 +602,88 @@ class FormattedExcinfo(object):
traceback = excinfo.traceback
if self.tbfilter:
traceback = traceback.filter()
recursionindex = None
if is_recursion_error(excinfo):
recursionindex = traceback.recursionindex()
traceback, extraline = self._truncate_recursive_traceback(traceback)
else:
extraline = None
last = traceback[-1]
entries = []
extraline = None
for index, entry in enumerate(traceback):
einfo = (last == entry) and excinfo or None
reprentry = self.repr_traceback_entry(entry, einfo)
entries.append(reprentry)
if index == recursionindex:
extraline = "!!! Recursion detected (same locals & position)"
break
return ReprTraceback(entries, extraline, style=self.style)
def repr_excinfo(self, excinfo):
reprtraceback = self.repr_traceback(excinfo)
reprcrash = excinfo._getreprcrash()
return ReprExceptionInfo(reprtraceback, reprcrash)
def _truncate_recursive_traceback(self, traceback):
"""
Truncate the given recursive traceback trying to find the starting point
of the recursion.
class TerminalRepr:
The detection is done by going through each traceback entry and finding the
point in which the locals of the frame are equal to the locals of a previous frame (see ``recursionindex()``.
Handle the situation where the recursion process might raise an exception (for example
comparing numpy arrays using equality raises a TypeError), in which case we do our best to
warn the user of the error and show a limited traceback.
"""
try:
recursionindex = traceback.recursionindex()
except Exception as e:
max_frames = 10
extraline = (
'!!! Recursion error detected, but an error occurred locating the origin of recursion.\n'
' The following exception happened when comparing locals in the stack frame:\n'
' {exc_type}: {exc_msg}\n'
' Displaying first and last {max_frames} stack frames out of {total}.'
).format(exc_type=type(e).__name__, exc_msg=safe_str(e), max_frames=max_frames, total=len(traceback))
traceback = traceback[:max_frames] + traceback[-max_frames:]
else:
extraline = "!!! Recursion detected (same locals & position)"
traceback = traceback[:recursionindex + 1]
return traceback, extraline
def repr_excinfo(self, excinfo):
if _PY2:
reprtraceback = self.repr_traceback(excinfo)
reprcrash = excinfo._getreprcrash()
return ReprExceptionInfo(reprtraceback, reprcrash)
else:
repr_chain = []
e = excinfo.value
descr = None
while e is not None:
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__)) 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__)) if e.__traceback__ else None
descr = 'During handling of the above exception, another exception occurred:'
else:
e = None
repr_chain.reverse()
return ExceptionChainRepr(repr_chain)
class TerminalRepr(object):
def __str__(self):
s = self.__unicode__()
if sys.version_info[0] < 3:
if _PY2:
s = s.encode('utf-8')
return s
@@ -617,21 +699,47 @@ class TerminalRepr:
return "<%s instance at %0x>" %(self.__class__, id(self))
class ReprExceptionInfo(TerminalRepr):
def __init__(self, reprtraceback, reprcrash):
self.reprtraceback = reprtraceback
self.reprcrash = reprcrash
class ExceptionRepr(TerminalRepr):
def __init__(self):
self.sections = []
def addsection(self, name, content, sep="-"):
self.sections.append((name, content, sep))
def toterminal(self, tw):
self.reprtraceback.toterminal(tw)
for name, content, sep in self.sections:
tw.sep(sep, name)
tw.line(content)
class ExceptionChainRepr(ExceptionRepr):
def __init__(self, chain):
super(ExceptionChainRepr, self).__init__()
self.chain = chain
# reprcrash and reprtraceback of the outermost (the newest) exception
# in the chain
self.reprtraceback = chain[-1][0]
self.reprcrash = chain[-1][1]
def toterminal(self, tw):
for element in self.chain:
element[0].toterminal(tw)
if element[2] is not None:
tw.line("")
tw.line(element[2], yellow=True)
super(ExceptionChainRepr, self).toterminal(tw)
class ReprExceptionInfo(ExceptionRepr):
def __init__(self, reprtraceback, reprcrash):
super(ReprExceptionInfo, self).__init__()
self.reprtraceback = reprtraceback
self.reprcrash = reprcrash
def toterminal(self, tw):
self.reprtraceback.toterminal(tw)
super(ReprExceptionInfo, self).toterminal(tw)
class ReprTraceback(TerminalRepr):
entrysep = "_ "
@@ -720,7 +828,8 @@ class ReprFileLocation(TerminalRepr):
i = msg.find("\n")
if i != -1:
msg = msg[:i]
tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
tw.write(self.path, bold=True, red=True)
tw.line(":%s: %s" % (self.lineno, msg))
class ReprLocals(TerminalRepr):
def __init__(self, lines):
@@ -753,29 +862,6 @@ class ReprFuncArgs(TerminalRepr):
tw.line("")
oldbuiltins = {}
def patch_builtins(assertion=True, compile=True):
""" put compile and AssertionError builtins to Python's builtins. """
if assertion:
from _pytest.assertion import reinterpret
l = oldbuiltins.setdefault('AssertionError', [])
l.append(py.builtin.builtins.AssertionError)
py.builtin.builtins.AssertionError = reinterpret.AssertionError
if compile:
import _pytest._code
l = oldbuiltins.setdefault('compile', [])
l.append(py.builtin.builtins.compile)
py.builtin.builtins.compile = _pytest._code.compile
def unpatch_builtins(assertion=True, compile=True):
""" remove compile and AssertionError builtins from Python builtins. """
if assertion:
py.builtin.builtins.AssertionError = oldbuiltins['AssertionError'].pop()
if compile:
py.builtin.builtins.compile = oldbuiltins['compile'].pop()
def getrawcode(obj, trycall=True):
""" return code object for given function. """
try:
@@ -792,7 +878,8 @@ def getrawcode(obj, trycall=True):
return x
return obj
if sys.version_info[:2] >= (3, 5): # RecursionError introduced in 3.5
if PY35: # RecursionError introduced in 3.5
def is_recursion_error(excinfo):
return excinfo.errisinstance(RecursionError) # noqa
else:

View File

@@ -1,10 +1,9 @@
from __future__ import generators
from __future__ import absolute_import, division, generators, print_function
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

@@ -2,7 +2,7 @@
imports symbols from vendored "pluggy" if available, otherwise
falls back to importing "pluggy" from the default namespace.
"""
from __future__ import absolute_import, division, print_function
try:
from _pytest.vendored_packages.pluggy import * # noqa
from _pytest.vendored_packages.pluggy import __version__ # noqa

View File

@@ -1,11 +1,13 @@
"""
support for presenting detailed information in failing assertions.
"""
from __future__ import absolute_import, division, print_function
import py
import os
import sys
from _pytest.monkeypatch import monkeypatch
from _pytest.assertion import util
from _pytest.assertion import rewrite
from _pytest.assertion import truncate
def pytest_addoption(parser):
@@ -13,25 +15,46 @@ def pytest_addoption(parser):
group.addoption('--assert',
action="store",
dest="assertmode",
choices=("rewrite", "reinterp", "plain",),
choices=("rewrite", "plain",),
default="rewrite",
metavar="MODE",
help="""control assertion debugging tools. 'plain'
performs no assertion debugging. 'reinterp'
reinterprets assert statements after they failed
to provide assertion expression information.
'rewrite' (the default) rewrites assert
statements in test modules on import to
provide assert expression information. """)
group.addoption('--no-assert',
action="store_true",
default=False,
dest="noassert",
help="DEPRECATED equivalent to --assert=plain")
group.addoption('--nomagic', '--no-magic',
action="store_true",
default=False,
help="DEPRECATED equivalent to --assert=plain")
help="""Control assertion debugging tools. 'plain'
performs no assertion debugging. 'rewrite'
(the default) rewrites assert statements in
test modules on import to provide assert
expression information.""")
def register_assert_rewrite(*names):
"""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
break
else:
importhook = DummyRewriteHook()
importhook.mark_rewrite(*names)
class DummyRewriteHook(object):
"""A no-op import hook for when rewriting is disabled."""
def mark_rewrite(self, *names):
pass
class AssertionState:
@@ -40,57 +63,39 @@ class AssertionState:
def __init__(self, config, mode):
self.mode = mode
self.trace = config.trace.root.get("assertion")
self.hook = None
def pytest_configure(config):
mode = config.getvalue("assertmode")
if config.getvalue("noassert") or config.getvalue("nomagic"):
mode = "plain"
if mode == "rewrite":
try:
import ast # noqa
except ImportError:
mode = "reinterp"
else:
# Both Jython and CPython 2.6.0 have AST bugs that make the
# assertion rewriting hook malfunction.
if (sys.platform.startswith('java') or
sys.version_info[:3] == (2, 6, 0)):
mode = "reinterp"
if mode != "plain":
_load_modules(mode)
m = monkeypatch()
config._cleanup.append(m.undo)
m.setattr(py.builtin.builtins, 'AssertionError',
reinterpret.AssertionError) # noqa
hook = None
if mode == "rewrite":
hook = rewrite.AssertionRewritingHook() # noqa
sys.meta_path.insert(0, hook)
warn_about_missing_assertion(mode)
config._assertstate = AssertionState(config, mode)
config._assertstate.hook = hook
config._assertstate.trace("configured with mode set to %r" % (mode,))
def install_importhook(config):
"""Try to install the rewrite hook, raise SystemError if it fails."""
# Both Jython and CPython 2.6.0 have AST bugs that make the
# assertion rewriting hook malfunction.
if (sys.platform.startswith('java') or
sys.version_info[:3] == (2, 6, 0)):
raise SystemError('rewrite not supported')
config._assertstate = AssertionState(config, 'rewrite')
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
def pytest_collection(session):
# this hook is only called when test modules are collected
# so for example not in the master process of pytest-xdist
# (which does not collect test modules)
hook = session.config._assertstate.hook
if hook is not None:
hook.set_session(session)
def _running_on_ci():
"""Check if we're currently running on a CI system."""
env_vars = ['CI', 'BUILD_NUMBER']
return any(var in os.environ for var in env_vars)
assertstate = getattr(session.config, '_assertstate', None)
if assertstate:
if assertstate.hook is not None:
assertstate.hook.set_session(session)
def pytest_runtest_setup(item):
@@ -106,8 +111,8 @@ def pytest_runtest_setup(item):
This uses the first result from the hook and then ensures the
following:
* Overly verbose explanations are dropped unless -vv was used or
running on a CI.
* Overly verbose explanations are truncated unless configured otherwise
(eg. if running in verbose mode).
* Embedded newlines are escaped to help util.format_explanation()
later.
* If the rewrite mode is used embedded %-characters are replaced
@@ -120,14 +125,7 @@ def pytest_runtest_setup(item):
config=item.config, op=op, left=left, right=right)
for new_expl in hook_result:
if new_expl:
if (sum(len(p) for p in new_expl[1:]) > 80*8 and
item.config.option.verbose < 2 and
not _running_on_ci()):
show_max = 10
truncated_lines = len(new_expl) - show_max
new_expl[show_max:] = [py.builtin._totext(
'Detailed information truncated (%d more lines)'
', use "-vv" to show' % truncated_lines)]
new_expl = truncate.truncate_if_required(new_expl, item)
new_expl = [line.replace("\n", "\\n") for line in new_expl]
res = py.builtin._totext("\n~").join(new_expl)
if item.config.getvalue("assertmode") == "rewrite":
@@ -141,35 +139,10 @@ def pytest_runtest_teardown(item):
def pytest_sessionfinish(session):
hook = session.config._assertstate.hook
if hook is not None:
hook.session = None
def _load_modules(mode):
"""Lazily import assertion related code."""
global rewrite, reinterpret
from _pytest.assertion import reinterpret # noqa
if mode == "rewrite":
from _pytest.assertion import rewrite # noqa
def warn_about_missing_assertion(mode):
try:
assert False
except AssertionError:
pass
else:
if mode == "rewrite":
specifically = ("assertions which are not in test modules "
"will be ignored")
else:
specifically = "failing tests may report as passing"
sys.stderr.write("WARNING: " + specifically +
" because assert statements are not executed "
"by the underlying Python interpreter "
"(are you using python -O?)\n")
assertstate = getattr(session.config, '_assertstate', None)
if assertstate:
if assertstate.hook is not None:
assertstate.hook.set_session(None)
# Expose this plugin's implementation for the pytest_assertrepr_compare hook

View File

@@ -1,407 +0,0 @@
"""
Find intermediate evalutation results in assert statements through builtin AST.
"""
import ast
import sys
import _pytest._code
import py
from _pytest.assertion import util
u = py.builtin._totext
class AssertionError(util.BuiltinAssertionError):
def __init__(self, *args):
util.BuiltinAssertionError.__init__(self, *args)
if args:
# on Python2.6 we get len(args)==2 for: assert 0, (x,y)
# on Python2.7 and above we always get len(args) == 1
# with args[0] being the (x,y) tuple.
if len(args) > 1:
toprint = args
else:
toprint = args[0]
try:
self.msg = u(toprint)
except Exception:
self.msg = u(
"<[broken __repr__] %s at %0xd>"
% (toprint.__class__, id(toprint)))
else:
f = _pytest._code.Frame(sys._getframe(1))
try:
source = f.code.fullsource
if source is not None:
try:
source = source.getstatement(f.lineno, assertion=True)
except IndexError:
source = None
else:
source = str(source.deindent()).strip()
except py.error.ENOENT:
source = None
# this can also occur during reinterpretation, when the
# co_filename is set to "<run>".
if source:
self.msg = reinterpret(source, f, should_fail=True)
else:
self.msg = "<could not determine information>"
if not self.args:
self.args = (self.msg,)
if sys.version_info > (3, 0):
AssertionError.__module__ = "builtins"
if sys.platform.startswith("java"):
# See http://bugs.jython.org/issue1497
_exprs = ("BoolOp", "BinOp", "UnaryOp", "Lambda", "IfExp", "Dict",
"ListComp", "GeneratorExp", "Yield", "Compare", "Call",
"Repr", "Num", "Str", "Attribute", "Subscript", "Name",
"List", "Tuple")
_stmts = ("FunctionDef", "ClassDef", "Return", "Delete", "Assign",
"AugAssign", "Print", "For", "While", "If", "With", "Raise",
"TryExcept", "TryFinally", "Assert", "Import", "ImportFrom",
"Exec", "Global", "Expr", "Pass", "Break", "Continue")
_expr_nodes = set(getattr(ast, name) for name in _exprs)
_stmt_nodes = set(getattr(ast, name) for name in _stmts)
def _is_ast_expr(node):
return node.__class__ in _expr_nodes
def _is_ast_stmt(node):
return node.__class__ in _stmt_nodes
else:
def _is_ast_expr(node):
return isinstance(node, ast.expr)
def _is_ast_stmt(node):
return isinstance(node, ast.stmt)
try:
_Starred = ast.Starred
except AttributeError:
# Python 2. Define a dummy class so isinstance() will always be False.
class _Starred(object): pass
class Failure(Exception):
"""Error found while interpreting AST."""
def __init__(self, explanation=""):
self.cause = sys.exc_info()
self.explanation = explanation
def reinterpret(source, frame, should_fail=False):
mod = ast.parse(source)
visitor = DebugInterpreter(frame)
try:
visitor.visit(mod)
except Failure:
failure = sys.exc_info()[1]
return getfailure(failure)
if should_fail:
return ("(assertion failed, but when it was re-run for "
"printing intermediate values, it did not fail. Suggestions: "
"compute assert expression before the assert or use --assert=plain)")
def run(offending_line, frame=None):
if frame is None:
frame = _pytest._code.Frame(sys._getframe(1))
return reinterpret(offending_line, frame)
def getfailure(e):
explanation = util.format_explanation(e.explanation)
value = e.cause[1]
if str(value):
lines = explanation.split('\n')
lines[0] += " << %s" % (value,)
explanation = '\n'.join(lines)
text = "%s: %s" % (e.cause[0].__name__, explanation)
if text.startswith('AssertionError: assert '):
text = text[16:]
return text
operator_map = {
ast.BitOr : "|",
ast.BitXor : "^",
ast.BitAnd : "&",
ast.LShift : "<<",
ast.RShift : ">>",
ast.Add : "+",
ast.Sub : "-",
ast.Mult : "*",
ast.Div : "/",
ast.FloorDiv : "//",
ast.Mod : "%",
ast.Eq : "==",
ast.NotEq : "!=",
ast.Lt : "<",
ast.LtE : "<=",
ast.Gt : ">",
ast.GtE : ">=",
ast.Pow : "**",
ast.Is : "is",
ast.IsNot : "is not",
ast.In : "in",
ast.NotIn : "not in"
}
unary_map = {
ast.Not : "not %s",
ast.Invert : "~%s",
ast.USub : "-%s",
ast.UAdd : "+%s"
}
class DebugInterpreter(ast.NodeVisitor):
"""Interpret AST nodes to gleam useful debugging information. """
def __init__(self, frame):
self.frame = frame
def generic_visit(self, node):
# Fallback when we don't have a special implementation.
if _is_ast_expr(node):
mod = ast.Expression(node)
co = self._compile(mod)
try:
result = self.frame.eval(co)
except Exception:
raise Failure()
explanation = self.frame.repr(result)
return explanation, result
elif _is_ast_stmt(node):
mod = ast.Module([node])
co = self._compile(mod, "exec")
try:
self.frame.exec_(co)
except Exception:
raise Failure()
return None, None
else:
raise AssertionError("can't handle %s" %(node,))
def _compile(self, source, mode="eval"):
return compile(source, "<assertion interpretation>", mode)
def visit_Expr(self, expr):
return self.visit(expr.value)
def visit_Module(self, mod):
for stmt in mod.body:
self.visit(stmt)
def visit_Name(self, name):
explanation, result = self.generic_visit(name)
# See if the name is local.
source = "%r in locals() is not globals()" % (name.id,)
co = self._compile(source)
try:
local = self.frame.eval(co)
except Exception:
# have to assume it isn't
local = None
if local is None or not self.frame.is_true(local):
return name.id, result
return explanation, result
def visit_Compare(self, comp):
left = comp.left
left_explanation, left_result = self.visit(left)
for op, next_op in zip(comp.ops, comp.comparators):
next_explanation, next_result = self.visit(next_op)
op_symbol = operator_map[op.__class__]
explanation = "%s %s %s" % (left_explanation, op_symbol,
next_explanation)
source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
co = self._compile(source)
try:
result = self.frame.eval(co, __exprinfo_left=left_result,
__exprinfo_right=next_result)
except Exception:
raise Failure(explanation)
try:
if not self.frame.is_true(result):
break
except KeyboardInterrupt:
raise
except:
break
left_explanation, left_result = next_explanation, next_result
if util._reprcompare is not None:
res = util._reprcompare(op_symbol, left_result, next_result)
if res:
explanation = res
return explanation, result
def visit_BoolOp(self, boolop):
is_or = isinstance(boolop.op, ast.Or)
explanations = []
for operand in boolop.values:
explanation, result = self.visit(operand)
explanations.append(explanation)
if result == is_or:
break
name = is_or and " or " or " and "
explanation = "(" + name.join(explanations) + ")"
return explanation, result
def visit_UnaryOp(self, unary):
pattern = unary_map[unary.op.__class__]
operand_explanation, operand_result = self.visit(unary.operand)
explanation = pattern % (operand_explanation,)
co = self._compile(pattern % ("__exprinfo_expr",))
try:
result = self.frame.eval(co, __exprinfo_expr=operand_result)
except Exception:
raise Failure(explanation)
return explanation, result
def visit_BinOp(self, binop):
left_explanation, left_result = self.visit(binop.left)
right_explanation, right_result = self.visit(binop.right)
symbol = operator_map[binop.op.__class__]
explanation = "(%s %s %s)" % (left_explanation, symbol,
right_explanation)
source = "__exprinfo_left %s __exprinfo_right" % (symbol,)
co = self._compile(source)
try:
result = self.frame.eval(co, __exprinfo_left=left_result,
__exprinfo_right=right_result)
except Exception:
raise Failure(explanation)
return explanation, result
def visit_Call(self, call):
func_explanation, func = self.visit(call.func)
arg_explanations = []
ns = {"__exprinfo_func" : func}
arguments = []
for arg in call.args:
arg_explanation, arg_result = self.visit(arg)
if isinstance(arg, _Starred):
arg_name = "__exprinfo_star"
ns[arg_name] = arg_result
arguments.append("*%s" % (arg_name,))
arg_explanations.append("*%s" % (arg_explanation,))
else:
arg_name = "__exprinfo_%s" % (len(ns),)
ns[arg_name] = arg_result
arguments.append(arg_name)
arg_explanations.append(arg_explanation)
for keyword in call.keywords:
arg_explanation, arg_result = self.visit(keyword.value)
if keyword.arg:
arg_name = "__exprinfo_%s" % (len(ns),)
keyword_source = "%s=%%s" % (keyword.arg)
arguments.append(keyword_source % (arg_name,))
arg_explanations.append(keyword_source % (arg_explanation,))
else:
arg_name = "__exprinfo_kwds"
arguments.append("**%s" % (arg_name,))
arg_explanations.append("**%s" % (arg_explanation,))
ns[arg_name] = arg_result
if getattr(call, 'starargs', None):
arg_explanation, arg_result = self.visit(call.starargs)
arg_name = "__exprinfo_star"
ns[arg_name] = arg_result
arguments.append("*%s" % (arg_name,))
arg_explanations.append("*%s" % (arg_explanation,))
if getattr(call, 'kwargs', None):
arg_explanation, arg_result = self.visit(call.kwargs)
arg_name = "__exprinfo_kwds"
ns[arg_name] = arg_result
arguments.append("**%s" % (arg_name,))
arg_explanations.append("**%s" % (arg_explanation,))
args_explained = ", ".join(arg_explanations)
explanation = "%s(%s)" % (func_explanation, args_explained)
args = ", ".join(arguments)
source = "__exprinfo_func(%s)" % (args,)
co = self._compile(source)
try:
result = self.frame.eval(co, **ns)
except Exception:
raise Failure(explanation)
pattern = "%s\n{%s = %s\n}"
rep = self.frame.repr(result)
explanation = pattern % (rep, rep, explanation)
return explanation, result
def _is_builtin_name(self, name):
pattern = "%r not in globals() and %r not in locals()"
source = pattern % (name.id, name.id)
co = self._compile(source)
try:
return self.frame.eval(co)
except Exception:
return False
def visit_Attribute(self, attr):
if not isinstance(attr.ctx, ast.Load):
return self.generic_visit(attr)
source_explanation, source_result = self.visit(attr.value)
explanation = "%s.%s" % (source_explanation, attr.attr)
source = "__exprinfo_expr.%s" % (attr.attr,)
co = self._compile(source)
try:
try:
result = self.frame.eval(co, __exprinfo_expr=source_result)
except AttributeError:
# Maybe the attribute name needs to be mangled?
if not attr.attr.startswith("__") or attr.attr.endswith("__"):
raise
source = "getattr(__exprinfo_expr.__class__, '__name__', '')"
co = self._compile(source)
class_name = self.frame.eval(co, __exprinfo_expr=source_result)
mangled_attr = "_" + class_name + attr.attr
source = "__exprinfo_expr.%s" % (mangled_attr,)
co = self._compile(source)
result = self.frame.eval(co, __exprinfo_expr=source_result)
except Exception:
raise Failure(explanation)
explanation = "%s\n{%s = %s.%s\n}" % (self.frame.repr(result),
self.frame.repr(result),
source_explanation, attr.attr)
# Check if the attr is from an instance.
source = "%r in getattr(__exprinfo_expr, '__dict__', {})"
source = source % (attr.attr,)
co = self._compile(source)
try:
from_instance = self.frame.eval(co, __exprinfo_expr=source_result)
except Exception:
from_instance = None
if from_instance is None or self.frame.is_true(from_instance):
rep = self.frame.repr(result)
pattern = "%s\n{%s = %s\n}"
explanation = pattern % (rep, rep, explanation)
return explanation, result
def visit_Assert(self, assrt):
test_explanation, test_result = self.visit(assrt.test)
explanation = "assert %s" % (test_explanation,)
if not self.frame.is_true(test_result):
try:
raise util.BuiltinAssertionError
except Exception:
raise Failure(explanation)
return explanation, test_result
def visit_Assign(self, assign):
value_explanation, value_result = self.visit(assign.value)
explanation = "... = %s" % (value_explanation,)
name = ast.Name("__exprinfo_expr", ast.Load(),
lineno=assign.value.lineno,
col_offset=assign.value.col_offset)
new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno,
col_offset=assign.col_offset)
mod = ast.Module([new_assign])
co = self._compile(mod, "exec")
try:
self.frame.exec_(co, __exprinfo_expr=value_result)
except Exception:
raise Failure(explanation)
return explanation, value_result

View File

@@ -1,6 +1,7 @@
"""Rewrite assertion AST to produce nice error messages"""
from __future__ import absolute_import, division, print_function
import ast
import _ast
import errno
import itertools
import imp
@@ -44,20 +45,20 @@ else:
class AssertionRewritingHook(object):
"""PEP302 Import hook which rewrites asserts."""
def __init__(self):
def __init__(self, config):
self.config = config
self.fnpats = config.getini("python_files")
self.session = None
self.modules = {}
self._rewritten_names = set()
self._register_with_pkg_resources()
self._must_rewrite = set()
def set_session(self, session):
self.fnpats = session.config.getini("python_files")
self.session = session
def find_module(self, name, path=None):
if self.session is None:
return None
sess = self.session
state = sess.config._assertstate
state = self.config._assertstate
state.trace("find_module called for: %s" % name)
names = name.rsplit(".", 1)
lastname = names[-1]
@@ -78,7 +79,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:
@@ -86,24 +92,13 @@ class AssertionRewritingHook(object):
return None
else:
fn = os.path.join(pth, name.rpartition(".")[2] + ".py")
fn_pypath = py.path.local(fn)
# Is this a test file?
if not sess.isinitpath(fn):
# We have to be very careful here because imports in this code can
# trigger a cycle.
self.session = None
try:
for pat in self.fnpats:
if fn_pypath.fnmatch(pat):
state.trace("matched test file %r" % (fn,))
break
else:
return None
finally:
self.session = sess
else:
state.trace("matched test file (was specified on cmdline): %r" %
(fn,))
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
@@ -140,7 +135,7 @@ class AssertionRewritingHook(object):
co = _read_pyc(fn_pypath, pyc, state.trace)
if co is None:
state.trace("rewriting %r" % (fn,))
source_stat, co = _rewrite_test(state, fn_pypath)
source_stat, co = _rewrite_test(self.config, fn_pypath)
if co is None:
# Probably a SyntaxError in the test.
return None
@@ -151,6 +146,55 @@ class AssertionRewritingHook(object):
self.modules[name] = co, pyc
return self
def _should_rewrite(self, name, fn_pypath, state):
# always rewrite conftest files
fn = str(fn_pypath)
if fn_pypath.basename == 'conftest.py':
state.trace("rewriting conftest file: %r" % (fn,))
return True
if self.session is not None:
if self.session.isinitpath(fn):
state.trace("matched test file (was specified on cmdline): %r" %
(fn,))
return True
# modules not passed explicitly on the command line are only
# rewritten if they match the naming convention for test files
for pat in self.fnpats:
# use fnmatch instead of fn_pypath.fnmatch because the
# latter might trigger an import to fnmatch.fnmatch
# internally, which would cause this method to be
# called recursively
if fn_pypath.fnmatch(pat):
state.trace("matched test file %r" % (fn,))
return True
for marked in self._must_rewrite:
if name.startswith(marked):
state.trace("matched marked file %r (from %r)" % (name, marked))
return True
return False
def mark_rewrite(self, *names):
"""Mark import names as needing to be re-written.
The named module or package as well as any nested modules will
be re-written on import.
"""
already_imported = set(names).intersection(set(sys.modules))
if 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, name):
self.config.warn(
'P1',
'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
# sys.modules, the loader must use that existing module. (Otherwise,
@@ -170,7 +214,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]
@@ -235,14 +280,16 @@ def _write_pyc(state, co, source_stat, pyc):
fp.close()
return True
RN = "\r\n".encode("utf-8")
N = "\n".encode("utf-8")
cookie_re = re.compile(r"^[ \t\f]*#.*coding[:=][ \t]*[-\w.]+")
BOM_UTF8 = '\xef\xbb\xbf'
def _rewrite_test(state, fn):
def _rewrite_test(config, fn):
"""Try to read and rewrite *fn* and return the code object."""
state = config._assertstate
try:
stat = fn.stat()
source = fn.read("rb")
@@ -287,9 +334,9 @@ def _rewrite_test(state, fn):
# Let this pop up again in the real import.
state.trace("failed to parse: %r" % (fn,))
return None, None
rewrite_asserts(tree)
rewrite_asserts(tree, fn, config)
try:
co = compile(tree, fn.strpath, "exec")
co = compile(tree, fn.strpath, "exec", dont_inherit=True)
except SyntaxError:
# It's possible that this error is from some bug in the
# assertion rewriting, but I don't know of a fast way to tell.
@@ -343,9 +390,9 @@ def _read_pyc(source, pyc, trace=lambda x: None):
return co
def rewrite_asserts(mod):
def rewrite_asserts(mod, module_path=None, config=None):
"""Rewrite the assert statements in mod."""
AssertionRewriter().run(mod)
AssertionRewriter(module_path, config).run(mod)
def _saferepr(obj):
@@ -532,6 +579,11 @@ class AssertionRewriter(ast.NodeVisitor):
"""
def __init__(self, module_path, config):
super(AssertionRewriter, self).__init__()
self.module_path = module_path
self.config = config
def run(self, mod):
"""Find all assert statements in *mod* and rewrite them."""
if not mod.body:
@@ -672,6 +724,10 @@ class AssertionRewriter(ast.NodeVisitor):
the expression is false.
"""
if isinstance(assert_.test, ast.Tuple) and self.config is not None:
fslocation = (self.module_path, assert_.lineno)
self.config.warn('R1', 'assertion is always true, perhaps '
'remove parentheses?', fslocation=fslocation)
self.statements = []
self.variables = []
self.variable_counter = itertools.count()
@@ -855,6 +911,8 @@ class AssertionRewriter(ast.NodeVisitor):
def visit_Compare(self, comp):
self.push_format_context()
left_res, left_expl = self.visit(comp.left)
if isinstance(comp.left, (_ast.Compare, _ast.BoolOp)):
left_expl = "({0})".format(left_expl)
res_variables = [self.variable() for i in range(len(comp.ops))]
load_names = [ast.Name(v, ast.Load()) for v in res_variables]
store_names = [ast.Name(v, ast.Store()) for v in res_variables]
@@ -864,6 +922,8 @@ class AssertionRewriter(ast.NodeVisitor):
results = [left_res]
for i, op, next_operand in it:
next_res, next_expl = self.visit(next_operand)
if isinstance(next_operand, (_ast.Compare, _ast.BoolOp)):
next_expl = "({0})".format(next_expl)
results.append(next_res)
sym = binop_map[op.__class__]
syms.append(ast.Str(sym))

View File

@@ -0,0 +1,102 @@
"""
Utilities for truncating assertion output.
Current default behaviour is to truncate assertion explanations at
~8 terminal lines, unless running in "-vv" mode or running on CI.
"""
from __future__ import absolute_import, division, print_function
import os
import py
DEFAULT_MAX_LINES = 8
DEFAULT_MAX_CHARS = 8 * 80
USAGE_MSG = "use '-vv' to show"
def truncate_if_required(explanation, item, max_length=None):
"""
Truncate this assertion explanation if the given test item is eligible.
"""
if _should_truncate_item(item):
return _truncate_explanation(explanation)
return explanation
def _should_truncate_item(item):
"""
Whether or not this test item is eligible for truncation.
"""
verbose = item.config.option.verbose
return verbose < 2 and not _running_on_ci()
def _running_on_ci():
"""Check if we're currently running on a CI system."""
env_vars = ['CI', 'BUILD_NUMBER']
return any(var in os.environ for var in env_vars)
def _truncate_explanation(input_lines, max_lines=None, max_chars=None):
"""
Truncate given list of strings that makes up the assertion explanation.
Truncates to either 8 lines, or 640 characters - whichever the input reaches
first. The remaining lines will be replaced by a usage message.
"""
if max_lines is None:
max_lines = DEFAULT_MAX_LINES
if max_chars is None:
max_chars = DEFAULT_MAX_CHARS
# Check if truncation required
input_char_count = len("".join(input_lines))
if len(input_lines) <= max_lines and input_char_count <= max_chars:
return input_lines
# Truncate first to max_lines, and then truncate to max_chars if max_chars
# is exceeded.
truncated_explanation = input_lines[:max_lines]
truncated_explanation = _truncate_by_char_count(truncated_explanation, max_chars)
# Add ellipsis to final line
truncated_explanation[-1] = truncated_explanation[-1] + "..."
# Append useful message to explanation
truncated_line_count = len(input_lines) - len(truncated_explanation)
truncated_line_count += 1 # Account for the part-truncated final line
msg = '...Full output truncated'
if truncated_line_count == 1:
msg += ' ({0} line hidden)'.format(truncated_line_count)
else:
msg += ' ({0} lines hidden)'.format(truncated_line_count)
msg += ", {0}" .format(USAGE_MSG)
truncated_explanation.extend([
py.builtin._totext(""),
py.builtin._totext(msg),
])
return truncated_explanation
def _truncate_by_char_count(input_lines, max_chars):
# Check if truncation required
if len("".join(input_lines)) <= max_chars:
return input_lines
# Find point at which input length exceeds total allowed length
iterated_char_count = 0
for iterated_index, input_line in enumerate(input_lines):
if iterated_char_count + len(input_line) > max_chars:
break
iterated_char_count += len(input_line)
# Create truncated explanation with modified final line
truncated_result = input_lines[:iterated_index]
final_line = input_lines[iterated_index]
if final_line:
final_line_truncate_point = max_chars - iterated_char_count
final_line = final_line[:final_line_truncate_point]
truncated_result.append(final_line)
return truncated_result

View File

@@ -1,4 +1,5 @@
"""Utilities for assertion debugging"""
from __future__ import absolute_import, division, print_function
import pprint
import _pytest._code
@@ -8,7 +9,7 @@ try:
except ImportError:
Sequence = list
BuiltinAssertionError = py.builtin.builtins.AssertionError
u = py.builtin._totext
# The _reprcompare attribute on the util module is used by the new assertion
@@ -38,44 +39,11 @@ def format_explanation(explanation):
displaying diffs.
"""
explanation = ecu(explanation)
explanation = _collapse_false(explanation)
lines = _split_explanation(explanation)
result = _format_lines(lines)
return u('\n').join(result)
def _collapse_false(explanation):
"""Collapse expansions of False
So this strips out any "assert False\n{where False = ...\n}"
blocks.
"""
where = 0
while True:
start = where = explanation.find("False\n{False = ", where)
if where == -1:
break
level = 0
prev_c = explanation[start]
for i, c in enumerate(explanation[start:]):
if prev_c + c == "\n{":
level += 1
elif prev_c + c == "\n}":
level -= 1
if not level:
break
prev_c = c
else:
raise AssertionError("unbalanced braces: %r" % (explanation,))
end = start + i
where = end
if explanation[end - 1] == '\n':
explanation = (explanation[:start] + explanation[start+15:end-1] +
explanation[end+1:])
where -= 17
return explanation
def _split_explanation(explanation):
"""Return a list of individual lines in the explanation
@@ -138,7 +106,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))
@@ -225,9 +193,10 @@ def _diff_text(left, right, verbose=False):
'characters in diff, use -v to show') % i]
left = left[:-i]
right = right[:-i]
keepends = True
explanation += [line.strip('\n')
for line in ndiff(left.splitlines(),
right.splitlines())]
for line in ndiff(left.splitlines(keepends),
right.splitlines(keepends))]
return explanation
@@ -288,8 +257,8 @@ def _compare_eq_dict(left, right, verbose=False):
explanation = []
common = set(left).intersection(set(right))
same = dict((k, left[k]) for k in common if left[k] == right[k])
if same and not verbose:
explanation += [u('Omitting %s identical items, use -v to show') %
if same and verbose < 2:
explanation += [u('Omitting %s identical items, use -vv to show') %
len(same)]
elif same:
explanation += [u('Common items:')]

View File

@@ -1,10 +1,10 @@
"""
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
"""
from __future__ import absolute_import, division, print_function
import py
import pytest
import json
@@ -139,11 +139,11 @@ class LFPlugin:
# running a subset of all tests with recorded failures outside
# of the set of tests currently executing
pass
elif self.config.getvalue("failedfirst"):
items[:] = previously_failed + previously_passed
else:
elif self.config.getvalue("lf"):
items[:] = previously_failed
config.hook.pytest_deselected(items=previously_passed)
else:
items[:] = previously_failed + previously_passed
def pytest_sessionfinish(self, session):
config = self.config
@@ -219,7 +219,7 @@ def cacheshow(config, session):
basedir = config.cache._cachedir
vdir = basedir.join("v")
tw.sep("-", "cache values")
for valpath in vdir.visit(lambda x: x.isfile()):
for valpath in sorted(vdir.visit(lambda x: x.isfile())):
key = valpath.relto(vdir).replace(valpath.sep, "/")
val = config.cache.get(key, dummy)
if val is dummy:
@@ -235,7 +235,7 @@ def cacheshow(config, session):
ddir = basedir.join("d")
if ddir.isdir() and ddir.listdir():
tw.sep("-", "cache directories")
for p in basedir.join("d").visit():
for p in sorted(basedir.join("d").visit()):
#if p.check(dir=1):
# print("%s/" % p.relto(basedir))
if p.isfile():

View File

@@ -2,16 +2,19 @@
per-test stdout/stderr capturing mechanism.
"""
from __future__ import with_statement
from __future__ import absolute_import, division, print_function
import contextlib
import sys
import os
import io
from io import UnsupportedOperation
from tempfile import TemporaryFile
import py
import pytest
from _pytest.compat import CaptureIO
from py.io import TextIO
unicode = py.builtin.text
patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
@@ -31,8 +34,10 @@ def pytest_addoption(parser):
@pytest.hookimpl(hookwrapper=True)
def pytest_load_initial_conftests(early_config, parser, args):
_readline_workaround()
ns = early_config.known_args_namespace
if ns.capture == "fd":
_py36_windowsconsoleio_workaround()
_readline_workaround()
pluginmanager = early_config.pluginmanager
capman = CaptureManager(ns.capture)
pluginmanager.register(capman, "capturemanager")
@@ -146,46 +151,48 @@ class CaptureManager:
def pytest_internalerror(self, excinfo):
self.reset_capturings()
def suspendcapture_item(self, item, when):
out, err = self.suspendcapture()
def suspendcapture_item(self, item, when, in_=False):
out, err = self.suspendcapture(in_=in_)
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"
@pytest.fixture
def capsys(request):
"""enables capturing of writes to sys.stdout/sys.stderr and makes
"""Enable capturing of writes to sys.stdout/sys.stderr and make
captured output available via ``capsys.readouterr()`` method calls
which return a ``(out, err)`` tuple.
"""
if "capfd" in request._funcargs:
if "capfd" in request.fixturenames:
raise request.raiseerror(error_capsysfderror)
request.node._capfuncarg = c = CaptureFixture(SysCapture)
request.node._capfuncarg = c = CaptureFixture(SysCapture, request)
return c
@pytest.fixture
def capfd(request):
"""enables capturing of writes to file descriptors 1 and 2 and makes
"""Enable capturing of writes to file descriptors 1 and 2 and make
captured output available via ``capfd.readouterr()`` method calls
which return a ``(out, err)`` tuple.
"""
if "capsys" in request._funcargs:
if "capsys" in request.fixturenames:
request.raiseerror(error_capsysfderror)
if not hasattr(os, 'dup'):
pytest.skip("capfd funcarg needs os.dup")
request.node._capfuncarg = c = CaptureFixture(FDCapture)
request.node._capfuncarg = c = CaptureFixture(FDCapture, request)
return c
class CaptureFixture:
def __init__(self, captureclass):
def __init__(self, captureclass, request):
self.captureclass = captureclass
self.request = request
def _start(self):
self._capture = MultiCapture(out=True, err=True, in_=False,
Capture=self.captureclass)
Capture=self.captureclass)
self._capture.start_capturing()
def close(self):
@@ -200,6 +207,15 @@ class CaptureFixture:
except AttributeError:
return self._outerr
@contextlib.contextmanager
def disabled(self):
capmanager = self.request.config.pluginmanager.getplugin('capturemanager')
capmanager.suspendcapture_item(self.request.node, "call", in_=True)
try:
yield
finally:
capmanager.resumecapture()
def safe_text_dupfile(f, mode, default_encoding="UTF8"):
""" return a open text file object that's a duplicate of f on the
@@ -390,7 +406,7 @@ class SysCapture:
if name == "stdin":
tmpfile = DontReadFromInput()
else:
tmpfile = TextIO()
tmpfile = CaptureIO()
self.tmpfile = tmpfile
def start(self):
@@ -436,7 +452,8 @@ class DontReadFromInput:
__iter__ = read
def fileno(self):
raise ValueError("redirected Stdin is pseudofile, has no fileno()")
raise UnsupportedOperation("redirected stdin is pseudofile, "
"has no fileno()")
def isatty(self):
return False
@@ -444,6 +461,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():
"""
@@ -452,7 +476,7 @@ def _readline_workaround():
Pdb uses readline support where available--when not running from the Python
prompt, the readline module is not imported until running the pdb REPL. If
running py.test with the --pdb option this means the readline module is not
running pytest with the --pdb option this means the readline module is not
imported until after I/O capture has been started.
This is a problem for pyreadline, which is often used to implement readline
@@ -470,3 +494,49 @@ def _readline_workaround():
import readline # noqa
except ImportError:
pass
def _py36_windowsconsoleio_workaround():
"""
Python 3.6 implemented unicode console handling for Windows. This works
by reading/writing to the raw console handle using
``{Read,Write}ConsoleW``.
The problem is that we are going to ``dup2`` over the stdio file
descriptors when doing ``FDCapture`` and this will ``CloseHandle`` the
handles used by Python to write to the console. Though there is still some
weirdness and the console handle seems to only be closed randomly and not
on the first call to ``CloseHandle``, or maybe it gets reopened with the
same handle value when we suspend capturing.
The workaround in this case will reopen stdio with a different fd which
also means a different handle by replicating the logic in
"Py_lifecycle.c:initstdio/create_stdio".
See https://github.com/pytest-dev/py/issues/103
"""
if not sys.platform.startswith('win32') or sys.version_info[:2] < (3, 6):
return
buffered = hasattr(sys.stdout.buffer, 'raw')
raw_stdout = sys.stdout.buffer.raw if buffered else sys.stdout.buffer
if not isinstance(raw_stdout, io._WindowsConsoleIO):
return
def _reopen_stdio(f, mode):
if not buffered and mode[0] == 'w':
buffering = 0
else:
buffering = -1
return io.TextIOWrapper(
open(os.dup(f.fileno()), mode, buffering),
f.encoding,
f.errors,
f.newlines,
f.line_buffering)
sys.__stdin__ = sys.stdin = _reopen_stdio(sys.stdin, 'rb')
sys.__stdout__ = sys.stdout = _reopen_stdio(sys.stdout, 'wb')
sys.__stderr__ = sys.stderr = _reopen_stdio(sys.stderr, 'wb')

307
_pytest/compat.py Normal file
View File

@@ -0,0 +1,307 @@
"""
python version compatibility code
"""
from __future__ import absolute_import, division, print_function
import sys
import inspect
import types
import re
import functools
import py
import _pytest
try:
import enum
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
NoneType = type(None)
NOTSET = object()
PY35 = sys.version_info[:2] >= (3, 5)
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))
else:
def _format_args(func):
return inspect.formatargspec(*inspect.getargspec(func))
isfunction = inspect.isfunction
isclass = inspect.isclass
# used to work around a python2 exception info leak
exc_clear = getattr(sys, 'exc_clear', lambda: None)
# The type of re.compile objects is not exposed in Python.
REGEX_TYPE = type(re.compile(''))
def is_generator(func):
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):
import inspect
fn = py.path.local(inspect.getfile(function))
lineno = py.builtin._getcode(function).co_firstlineno
if fn.relto(curdir):
fn = fn.relto(curdir)
return "%s:%d" %(fn, lineno+1)
def num_mock_patch_args(function):
""" return number of arguments used up by mock arguments (if any) """
patchings = getattr(function, "patchings", None)
if not patchings:
return 0
mock = sys.modules.get("mock", sys.modules.get("unittest.mock", None))
if mock is not None:
return len([p for p in patchings
if not p.attribute_name and p.new is mock.DEFAULT])
return len(patchings)
def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames
#assert not isclass(function)
realfunction = function
while hasattr(realfunction, "__wrapped__"):
realfunction = realfunction.__wrapped__
if startindex is None:
startindex = inspect.ismethod(function) and 1 or 0
if realfunction != function:
startindex += num_mock_patch_args(function)
function = realfunction
if isinstance(function, functools.partial):
argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
partial = function
argnames = argnames[len(partial.args):]
if partial.keywords:
for kw in partial.keywords:
argnames.remove(kw)
else:
argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
defaults = getattr(function, 'func_defaults',
getattr(function, '__defaults__', None)) or ()
numdefaults = len(defaults)
if numdefaults:
return tuple(argnames[startindex:-numdefaults])
return tuple(argnames[startindex:])
if sys.version_info[:2] == (2, 6):
def isclass(object):
""" Return true if the object is a class. Overrides inspect.isclass for
python 2.6 because it will return True for objects which always return
something on __getattr__ calls (see #1035).
Backport of https://hg.python.org/cpython/rev/35bf8f7a8edc
"""
return isinstance(object, (type, types.ClassType))
if _PY3:
import codecs
imap = map
STRING_TYPES = bytes, str
UNICODE_TYPES = str,
def _escape_strings(val):
"""If val is pure ascii, returns it as a str(). Otherwise, escapes
bytes objects into a sequence of escaped bytes:
b'\xc3\xb4\xc5\xd6' -> u'\\xc3\\xb4\\xc5\\xd6'
and escapes unicode objects into a sequence of escaped unicode
ids, e.g.:
'4\\nV\\U00043efa\\x0eMXWB\\x1e\\u3028\\u15fd\\xcd\\U0007d944'
note:
the obvious "v.decode('unicode-escape')" will return
valid utf-8 unicode if it finds them in bytes, but we
want to return escaped bytes for any byte, even if they match
a utf-8 string.
"""
if isinstance(val, bytes):
if val:
# source: http://goo.gl/bGsnwC
encoded_bytes, _ = codecs.escape_encode(val)
return encoded_bytes.decode('ascii')
else:
# empty bytes crashes codecs.escape_encode (#1087)
return ''
else:
return val.encode('unicode_escape').decode('ascii')
else:
STRING_TYPES = bytes, str, unicode
UNICODE_TYPES = unicode,
from itertools import imap # NOQA
def _escape_strings(val):
"""In py2 bytes and str are the same type, so return if it's a bytes
object, return it unchanged if it is a full ascii string,
otherwise escape it into its binary form.
If it's a unicode string, change the unicode characters into
unicode escapes.
"""
if isinstance(val, bytes):
try:
return val.encode('ascii')
except UnicodeDecodeError:
return val.encode('string-escape')
else:
return val.encode('unicode-escape')
def get_real_func(obj):
""" gets the real function object of the (possibly) wrapped object by
functools.wraps or functools.partial.
"""
start_obj = obj
for i in range(100):
new_obj = getattr(obj, '__wrapped__', None)
if new_obj is None:
break
obj = new_obj
else:
raise ValueError(
("could not find real function of {start}"
"\nstopped at {current}").format(
start=py.io.saferepr(start_obj),
current=py.io.saferepr(obj)))
if isinstance(obj, functools.partial):
obj = obj.func
return obj
def getfslineno(obj):
# xxx let decorators etc specify a sane ordering
obj = get_real_func(obj)
if hasattr(obj, 'place_as'):
obj = obj.place_as
fslineno = _pytest._code.getfslineno(obj)
assert isinstance(fslineno[1], int), obj
return fslineno
def getimfunc(func):
try:
return func.__func__
except AttributeError:
try:
return func.im_func
except AttributeError:
return func
def safe_getattr(object, name, default):
""" Like getattr but return default upon any Exception.
Attribute access can potentially fail for 'evil' Python objects.
See issue #214.
"""
try:
return getattr(object, name, default)
except Exception:
return default
def _is_unittest_unexpected_success_a_failure():
"""Return if the test suite should fail if a @expectedFailure unittest test PASSES.
From https://docs.python.org/3/library/unittest.html?highlight=unittest#unittest.TestResult.wasSuccessful:
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)
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:
if not isinstance(v, unicode):
v = unicode(v)
errors = 'replace'
return v.encode('utf-8', errors)
COLLECT_FAKEMODULE_ATTRIBUTES = (
'Collector',
'Module',
'Generator',
'Function',
'Instance',
'Session',
'Item',
'Class',
'File',
'_fillfuncargs',
)
def _setup_collect_fakemodule():
from types import ModuleType
import pytest
pytest.collect = ModuleType('pytest.collect')
pytest.collect.__all__ = [] # used for setns
for attr in COLLECT_FAKEMODULE_ATTRIBUTES:
setattr(pytest.collect, attr, getattr(pytest, attr))
if _PY2:
from py.io import TextIO as CaptureIO
else:
import io
class CaptureIO(io.TextIOWrapper):
def __init__(self):
super(CaptureIO, self).__init__(
io.BytesIO(),
encoding='UTF-8', newline='', write_through=True,
)
def getvalue(self):
return self.buffer.getvalue().decode('UTF-8')
class FuncargnamesCompatAttr(object):
""" helper class so that Metafunc, Function and FixtureRequest
don't need to each define the "funcargnames" compatibility attribute.
"""
@property
def funcargnames(self):
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
return self.fixturenames

View File

@@ -1,4 +1,5 @@
""" command line options, ini-file and conftest.py processing. """
from __future__ import absolute_import, division, print_function
import argparse
import shlex
import traceback
@@ -7,10 +8,13 @@ import warnings
import py
# DON't import pytest here because it causes import cycle troubles
import sys, os
import sys
import os
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")
@@ -25,6 +29,12 @@ class ConftestImportFailure(Exception):
self.path = path
self.excinfo = excinfo
def __str__(self):
etype, evalue, etb = self.excinfo
formatted = traceback.format_tb(etb)
# The level of the tracebacks we want to print is hand crafted :(
return repr(evalue) + '\n' + ''.join(formatted[2:])
def main(args=None, plugins=None):
""" return exit code, after performing an in-process test run.
@@ -45,7 +55,6 @@ def main(args=None, plugins=None):
return 4
else:
try:
config.pluginmanager.check_pending()
return config.hook.pytest_cmdline_main(config=config)
finally:
config._ensure_unconfigure()
@@ -57,15 +66,47 @@ def main(args=None, plugins=None):
class cmdline: # compatibility namespace
main = staticmethod(main)
class UsageError(Exception):
""" error in pytest usage or invocation"""
class PrintHelp(Exception):
"""Raised when pytest should print it's help to skip the rest of the
argument parsing and validation."""
pass
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 = (
"mark main terminal runner python pdb unittest capture skipping "
"tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript "
"junitxml resultlog doctest cacheprovider").split()
"mark main terminal runner python fixtures debugging unittest capture skipping "
"tmpdir monkeypatch recwarn pastebin helpconfig nose assertion "
"junitxml resultlog doctest cacheprovider freeze_support "
"setuponly setupplan warnings").split()
builtin_plugins = set(default_plugins)
builtin_plugins.add("pytester")
@@ -97,6 +138,7 @@ def get_plugin_manager():
return get_config().pluginmanager
def _prepareconfig(args=None, plugins=None):
warning = None
if args is None:
args = sys.argv[1:]
elif isinstance(args, py.path.local):
@@ -105,6 +147,8 @@ def _prepareconfig(args=None, plugins=None):
if not isinstance(args, str):
raise ValueError("not a string or argument list: %r" % (args,))
args = shlex.split(args, posix=sys.platform != "win32")
from _pytest import deprecated
warning = deprecated.MAIN_STR_ARGS
config = get_config()
pluginmanager = config.pluginmanager
try:
@@ -114,6 +158,8 @@ def _prepareconfig(args=None, plugins=None):
pluginmanager.consider_pluginarg(plugin)
else:
pluginmanager.register(plugin)
if warning:
config.warn('C1', warning)
return pluginmanager.hook.pytest_cmdline_parse(
pluginmanager=pluginmanager, args=args)
except BaseException:
@@ -123,7 +169,7 @@ def _prepareconfig(args=None, plugins=None):
class PytestPluginManager(PluginManager):
"""
Overwrites :py:class:`pluggy.PluginManager` to add pytest-specific
Overwrites :py:class:`pluggy.PluginManager <_pytest.vendored_packages.pluggy.PluginManager>` to add pytest-specific
functionality:
* loading plugins from the command line, ``PYTEST_PLUGIN`` env variable and
@@ -139,6 +185,7 @@ class PytestPluginManager(PluginManager):
self._conftestpath2mod = {}
self._confcutdir = None
self._noconftest = False
self._duplicatepaths = set()
self.add_hookspecs(_pytest.hookspec)
self.register(self)
@@ -152,11 +199,14 @@ class PytestPluginManager(PluginManager):
self.trace.root.setwriter(err.write)
self.enable_tracing()
# Config._consider_importhook will set a real object if required.
self.rewrite_hook = _pytest.assertion.DummyRewriteHook()
def addhooks(self, module_or_class):
"""
.. deprecated:: 2.8
Use :py:meth:`pluggy.PluginManager.add_hookspecs` instead.
Use :py:meth:`pluggy.PluginManager.add_hookspecs <_pytest.vendored_packages.pluggy.PluginManager.add_hookspecs>` instead.
"""
warning = dict(code="I2",
fslocation=_pytest._code.getfslineno(sys._getframe(1)),
@@ -209,6 +259,9 @@ class PytestPluginManager(PluginManager):
if ret:
self.hook.pytest_plugin_registered.call_historic(
kwargs=dict(plugin=plugin, manager=self))
if isinstance(plugin, types.ModuleType):
self.consider_module(plugin)
return ret
def getplugin(self, name):
@@ -353,38 +406,37 @@ class PytestPluginManager(PluginManager):
self.import_plugin(arg)
def consider_conftest(self, conftestmodule):
if self.register(conftestmodule, name=conftestmodule.__file__):
self.consider_module(conftestmodule)
self.register(conftestmodule, name=conftestmodule.__file__)
def consider_env(self):
self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
def consider_module(self, mod):
self._import_plugin_specs(getattr(mod, "pytest_plugins", None))
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, (py.builtin.text, str)), "module name as text required, got %r" % modname
modname = str(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):
@@ -398,7 +450,24 @@ class PytestPluginManager(PluginManager):
else:
mod = sys.modules[importspec]
self.register(mod, modname)
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:
@@ -537,13 +606,18 @@ class ArgumentError(Exception):
class Argument:
"""class that mimics the necessary behaviour of optparse.Option """
"""class that mimics the necessary behaviour of optparse.Option
its currently a least effort implementation
and ignoring choices and integer prefixes
https://docs.python.org/3/library/optparse.html#optparse-standard-option-types
"""
_typ_map = {
'int': int,
'string': str,
}
# enable after some grace period for plugin writers
TYPE_WARN = False
'float': float,
'complex': complex,
}
def __init__(self, *names, **attrs):
"""store parms in private vars for use in add_argument"""
@@ -551,17 +625,12 @@ class Argument:
self._short_opts = []
self._long_opts = []
self.dest = attrs.get('dest')
if self.TYPE_WARN:
try:
help = attrs['help']
if '%default' in help:
warnings.warn(
'pytest now uses argparse. "%default" should be'
' changed to "%(default)s" ',
FutureWarning,
stacklevel=3)
except KeyError:
pass
if '%default' in (attrs.get('help') or ''):
warnings.warn(
'pytest now uses argparse. "%default" should be'
' changed to "%(default)s" ',
DeprecationWarning,
stacklevel=3)
try:
typ = attrs['type']
except KeyError:
@@ -570,25 +639,23 @@ class Argument:
# this might raise a keyerror as well, don't want to catch that
if isinstance(typ, py.builtin._basestring):
if typ == 'choice':
if self.TYPE_WARN:
warnings.warn(
'type argument to addoption() is a string %r.'
' For parsearg this is optional and when supplied '
' should be a type.'
' (options: %s)' % (typ, names),
FutureWarning,
stacklevel=3)
warnings.warn(
'type argument to addoption() is a string %r.'
' For parsearg this is optional and when supplied'
' should be a type.'
' (options: %s)' % (typ, names),
DeprecationWarning,
stacklevel=3)
# argparse expects a type here take it from
# the type of the first element
attrs['type'] = type(attrs['choices'][0])
else:
if self.TYPE_WARN:
warnings.warn(
'type argument to addoption() is a string %r.'
' For parsearg this should be a type.'
' (options: %s)' % (typ, names),
FutureWarning,
stacklevel=3)
warnings.warn(
'type argument to addoption() is a string %r.'
' For parsearg this should be a type.'
' (options: %s)' % (typ, names),
DeprecationWarning,
stacklevel=3)
attrs['type'] = Argument._typ_map[typ]
# used in test_parseopt -> test_parse_defaultgetter
self.type = attrs['type']
@@ -655,20 +722,17 @@ class Argument:
self._long_opts.append(opt)
def __repr__(self):
retval = 'Argument('
args = []
if self._short_opts:
retval += '_short_opts: ' + repr(self._short_opts) + ', '
args += ['_short_opts: ' + repr(self._short_opts)]
if self._long_opts:
retval += '_long_opts: ' + repr(self._long_opts) + ', '
retval += 'dest: ' + repr(self.dest) + ', '
args += ['_long_opts: ' + repr(self._long_opts)]
args += ['dest: ' + repr(self.dest)]
if hasattr(self, 'type'):
retval += 'type: ' + repr(self.type) + ', '
args += ['type: ' + repr(self.type)]
if hasattr(self, 'default'):
retval += 'default: ' + repr(self.default) + ', '
if retval[-2:] == ', ': # always long enough to test ("Argument(" )
retval = retval[:-2]
retval += ')'
return retval
args += ['default: ' + repr(self.default)]
return 'Argument({0})'.format(', '.join(args))
class OptionGroup:
@@ -686,6 +750,10 @@ class OptionGroup:
results in help showing '--two-words' only, but --twowords gets
accepted **and** the automatic destination is in args.twowords
"""
conflict = set(optnames).intersection(
name for opt in self.options for name in opt.names())
if conflict:
raise ValueError("option names %s already added" % conflict)
option = Argument(*optnames, **attrs)
self._addoption_instance(option, shortupper=False)
@@ -772,7 +840,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
@@ -797,9 +865,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. """
@@ -817,14 +887,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))
@@ -847,11 +920,11 @@ class Config(object):
fin = self._cleanup.pop()
fin()
def warn(self, code, message, fslocation=None):
def warn(self, code, message, fslocation=None, nodeid=None):
""" generate a warning for this test session. """
self.hook.pytest_logwarning.call_historic(kwargs=dict(
code=code, message=message,
fslocation=fslocation, nodeid=None))
fslocation=fslocation, nodeid=nodeid))
def get_terminal_writer(self):
return self.pluginmanager.get_plugin("terminalreporter")._tw
@@ -908,13 +981,81 @@ class Config(object):
def _initini(self, args):
ns, unknown_args = self._parser.parse_known_and_unknown_args(args, namespace=self.option.copy())
r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args)
r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args, warnfunc=self.warn)
self.rootdir, self.inifile, self.inicfg = r
self._parser.extra_info['rootdir'] = self.rootdir
self._parser.extra_info['inifile'] = self.inifile
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):
"""Install the PEP 302 import hook if using assertion re-writing.
Needs to parse the --assert=<mode> option from the commandline
and find all the installed plugins to mark them for re-writing
by the importhook.
"""
ns, unknown_args = self._parser.parse_known_and_unknown_args(args)
mode = ns.assertmode
if mode == 'rewrite':
try:
hook = _pytest.assertion.install_importhook(self)
except SystemError:
mode = 'plain'
else:
self._mark_plugins_for_rewrite(hook)
self._warn_about_missing_assertion(mode)
def _mark_plugins_for_rewrite(self, hook):
"""
Given an importhook, mark for rewrite any top-level
modules or packages in the distribution package for
all pytest plugins.
"""
import pkg_resources
self.pluginmanager.rewrite_hook = hook
# '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
metadata_files = 'RECORD', 'SOURCES.txt'
package_files = (
entry.split(',')[0]
for entrypoint in pkg_resources.iter_entry_points('pytest11')
for metadata in metadata_files
for entry in entrypoint.dist._get_metadata(metadata)
)
for fn in package_files:
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)
def _warn_about_missing_assertion(self, mode):
try:
assert False
except AssertionError:
pass
else:
if mode == 'plain':
sys.stderr.write("WARNING: ASSERTIONS ARE NOT EXECUTED"
" and FAILING TESTS WILL PASS. Are you"
" using python -O?")
else:
sys.stderr.write("WARNING: assertions not in test modules or"
" plugins will be ignored"
" because assert statements are not executed "
"by the underlying Python interpreter "
"(are you using python -O?)\n")
def _preparse(self, args, addopts=True):
self._initini(args)
@@ -922,13 +1063,12 @@ class Config(object):
args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
args[:] = self.getini("addopts") + args
self._checkversion()
self._consider_importhook(args)
self.pluginmanager.consider_preparse(args)
try:
self.pluginmanager.load_setuptools_entrypoints("pytest11")
except ImportError as e:
self.warn("I2", "could not load setuptools entry import: %s" % (e,))
self.pluginmanager.load_setuptools_entrypoints('pytest11')
self.pluginmanager.consider_env()
self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
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
@@ -966,14 +1106,18 @@ class Config(object):
self._preparse(args, addopts=addopts)
# XXX deprecated hook:
self.hook.pytest_cmdline_preparse(config=self, args=args)
args = self._parser.parse_setoption(args, self.option, namespace=self.option)
if not args:
cwd = os.getcwd()
if cwd == self.rootdir:
args = self.getini('testpaths')
self._parser.after_preparse = True
try:
args = self._parser.parse_setoption(args, self.option, namespace=self.option)
if not args:
args = [cwd]
self.args = args
cwd = os.getcwd()
if cwd == self.rootdir:
args = self.getini('testpaths')
if not args:
args = [cwd]
self.args = args
except PrintHelp:
pass
def addinivalue_line(self, name, line):
""" add a line to an ini-file option. The option must have been
@@ -986,7 +1130,7 @@ class Config(object):
def getini(self, name):
""" return configuration value from an :ref:`ini file <inifiles>`. If the
specified name hasn't been registered through a prior
:py:func:`parser.addini <pytest.config.Parser.addini>`
:py:func:`parser.addini <_pytest.config.Parser.addini>`
call (usually from a plugin), a ValueError is raised. """
try:
return self._inicache[name]
@@ -999,14 +1143,16 @@ class Config(object):
description, type, default = self._parser._inidict[name]
except KeyError:
raise ValueError("unknown configuration value: %r" %(name,))
try:
value = self.inicfg[name]
except KeyError:
if default is not None:
return default
if type is None:
return ''
return []
value = self._get_override_ini_value(name)
if value is None:
try:
value = self.inicfg[name]
except KeyError:
if default is not None:
return default
if type is None:
return ''
return []
if type == "pathlist":
dp = py.path.local(self.inicfg.config.path).dirpath()
l = []
@@ -1037,6 +1183,22 @@ class Config(object):
l.append(relroot)
return l
def _get_override_ini_value(self, name):
value = None
# override_ini is a list of list, to support both -o foo1=bar1 foo2=bar2 and
# 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
for ini_config_list in self._override_ini:
for ini_config in ini_config_list:
try:
(key, user_ini_value) = ini_config.split("=", 1)
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):
""" return command line option value.
@@ -1074,7 +1236,18 @@ def exists(path, ignore=EnvironmentError):
except ignore:
return False
def getcfg(args, inibasenames):
def getcfg(args, warnfunc=None):
"""
Search the list of arguments for a valid ini-file for pytest,
and return a tuple of (rootdir, inifile, cfg-dict).
note: warnfunc is an optional function used to warn
about ini-files that use deprecated features.
This parameter should be removed when pytest
adopts standard deprecation warnings (#1804).
"""
from _pytest.deprecated import SETUP_CFG_PYTEST
inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"]
args = [x for x in args if not str(x).startswith("-")]
if not args:
args = [py.path.local()]
@@ -1086,57 +1259,89 @@ def getcfg(args, inibasenames):
if exists(p):
iniconfig = py.iniconfig.IniConfig(p)
if 'pytest' in iniconfig.sections:
if inibasename == 'setup.cfg' and warnfunc:
warnfunc('C1', SETUP_CFG_PYTEST)
return base, p, iniconfig['pytest']
if inibasename == 'setup.cfg' and 'tool:pytest' in iniconfig.sections:
return base, p, iniconfig['tool:pytest']
elif inibasename == "pytest.ini":
# allowed to be empty
return base, p, {}
return None, None, None
def get_common_ancestor(args):
# args are what we get after early command line parsing (usually
# strings, but can be py.path.local objects as well)
def get_common_ancestor(paths):
common_ancestor = None
for arg in args:
if str(arg)[0] == "-":
for path in paths:
if not path.exists():
continue
p = py.path.local(arg)
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:
common_ancestor = py.path.local()
elif not common_ancestor.isdir():
elif common_ancestor.isfile():
common_ancestor = common_ancestor.dirpath()
return common_ancestor
def determine_setup(inifile, args):
def get_dirs_from_args(args):
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):
dirs = get_dirs_from_args(args)
if inifile:
iniconfig = py.iniconfig.IniConfig(inifile)
try:
inicfg = iniconfig["pytest"]
except KeyError:
inicfg = None
rootdir = get_common_ancestor(args)
rootdir = get_common_ancestor(dirs)
else:
ancestor = get_common_ancestor(args)
rootdir, inifile, inicfg = getcfg(
[ancestor], ["pytest.ini", "tox.ini", "setup.cfg"])
ancestor = get_common_ancestor(dirs)
rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc)
if rootdir is None:
for rootdir in ancestor.parts(reverse=True):
if rootdir.join("setup.py").exists():
break
else:
rootdir = ancestor
rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc)
if rootdir is None:
rootdir = get_common_ancestor([py.path.local(), ancestor])
is_fs_root = os.path.splitdrive(str(rootdir))[1] == os.sep
if is_fs_root:
rootdir = ancestor
return rootdir, inifile, inicfg or {}

View File

@@ -1,51 +1,65 @@
""" interactive debugging with PDB, the Python Debugger. """
from __future__ import absolute_import
from __future__ import absolute_import, division, print_function
import pdb
import sys
import pytest
def pytest_addoption(parser):
group = parser.getgroup("general")
group._addoption('--pdb',
action="store_true", dest="usepdb", default=False,
help="start the interactive Python debugger on errors.")
group._addoption(
'--pdb', dest="usepdb", action="store_true",
help="start the interactive Python debugger on errors.")
group._addoption(
'--pdbcls', dest="usepdb_cls", metavar="modulename:classname",
help="start a custom interactive Python debugger on errors. "
"For example: --pdbcls=IPython.terminal.debugger:TerminalPdb")
def pytest_namespace():
return {'set_trace': pytestPDB().set_trace}
def pytest_configure(config):
if config.getvalue("usepdb_cls"):
modname, classname = config.getvalue("usepdb_cls").split(":")
__import__(modname)
pdb_cls = getattr(sys.modules[modname], classname)
else:
pdb_cls = pdb.Pdb
if config.getvalue("usepdb"):
config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
old = (pdb.set_trace, pytestPDB._pluginmanager)
def fin():
pdb.set_trace, pytestPDB._pluginmanager = old
pytestPDB._config = None
pdb.set_trace = pytest.set_trace
pytestPDB._pdb_cls = pdb.Pdb
pdb.set_trace = pytestPDB.set_trace
pytestPDB._pluginmanager = config.pluginmanager
pytestPDB._config = config
pytestPDB._pdb_cls = pdb_cls
config._cleanup.append(fin)
class pytestPDB:
""" Pseudo PDB that defers to the real pdb. """
_pluginmanager = None
_config = None
_pdb_cls = pdb.Pdb
def set_trace(self):
@classmethod
def set_trace(cls):
""" invoke PDB set_trace debugging, dropping any IO capturing. """
import _pytest.config
frame = sys._getframe().f_back
if self._pluginmanager is not None:
capman = self._pluginmanager.getplugin("capturemanager")
if cls._pluginmanager is not None:
capman = cls._pluginmanager.getplugin("capturemanager")
if capman:
capman.suspendcapture(in_=True)
tw = _pytest.config.create_terminal_writer(self._config)
tw = _pytest.config.create_terminal_writer(cls._config)
tw.line()
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
self._pluginmanager.hook.pytest_enter_pdb(config=self._config)
pdb.Pdb().set_trace(frame)
cls._pluginmanager.hook.pytest_enter_pdb(config=cls._config)
cls._pdb_cls().set_trace(frame)
class PdbInvoke:
@@ -59,7 +73,7 @@ class PdbInvoke:
def pytest_internalerror(self, excrepr, excinfo):
for line in str(excrepr).split("\n"):
sys.stderr.write("INTERNALERROR> %s\n" %line)
sys.stderr.write("INTERNALERROR> %s\n" % line)
sys.stderr.flush()
tb = _postmortem_traceback(excinfo)
post_mortem(tb)
@@ -98,7 +112,7 @@ def _find_last_non_hidden_frame(stack):
def post_mortem(t):
class Pdb(pdb.Pdb):
class Pdb(pytestPDB._pdb_cls):
def get_stack(self, f, t):
stack, i = pdb.Pdb.get_stack(self, f, t)
if f is None:

24
_pytest/deprecated.py Normal file
View File

@@ -0,0 +1,24 @@
"""
This module contains deprecation messages and bits of code used elsewhere in the codebase
that is planned to be removed in the next pytest release.
Keeping it in a central location makes it easy to track what is deprecated and should
be removed when the time comes.
"""
from __future__ import absolute_import, division, print_function
MAIN_STR_ARGS = 'passing a string to pytest.main() is deprecated, ' \
'pass a list of arguments instead.'
YIELD_TESTS = 'yield tests are deprecated, and scheduled to be removed in pytest 4.0'
FUNCARG_PREFIX = (
'{name}: declaring fixtures using "pytest_funcarg__" prefix is deprecated '
'and scheduled to be removed in pytest 4.0. '
'Please remove the prefix and use the @pytest.fixture decorator instead.')
SETUP_CFG_PYTEST = '[pytest] section in setup.cfg files is deprecated, use [tool:pytest] instead.'
GETFUNCARGVALUE = "use of getfuncargvalue is deprecated, use getfixturevalue"
RESULT_LOG = '--result-log is deprecated and scheduled for removal in pytest 4.0'

View File

@@ -1,22 +1,41 @@
""" discover and run doctests in modules and test files."""
from __future__ import absolute_import
from __future__ import absolute_import, division, print_function
import traceback
import pytest
from _pytest._code.code import TerminalRepr, ReprFileLocation, ExceptionInfo
from _pytest.python import FixtureRequest
from _pytest._code.code import ExceptionInfo, ReprFileLocation, TerminalRepr
from _pytest.fixtures import FixtureRequest
DOCTEST_REPORT_CHOICE_NONE = 'none'
DOCTEST_REPORT_CHOICE_CDIFF = 'cdiff'
DOCTEST_REPORT_CHOICE_NDIFF = 'ndiff'
DOCTEST_REPORT_CHOICE_UDIFF = 'udiff'
DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE = 'only_first_failure'
DOCTEST_REPORT_CHOICES = (
DOCTEST_REPORT_CHOICE_NONE,
DOCTEST_REPORT_CHOICE_CDIFF,
DOCTEST_REPORT_CHOICE_NDIFF,
DOCTEST_REPORT_CHOICE_UDIFF,
DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE,
)
def pytest_addoption(parser):
parser.addini('doctest_optionflags', 'option flags for doctests',
type="args", default=["ELLIPSIS"])
parser.addini("doctest_encoding", 'encoding used for doctest files', default="utf-8")
group = parser.getgroup("collect")
group.addoption("--doctest-modules",
action="store_true", default=False,
help="run doctests in all .py modules",
dest="doctestmodules")
group.addoption("--doctest-report",
type=str.lower, default="udiff",
help="choose another output format for diffs on doctest failure",
choices=DOCTEST_REPORT_CHOICES,
dest="doctestreport")
group.addoption("--doctest-glob",
action="append", default=[], metavar="pat",
help="doctests file matching pattern, default: test*.txt",
@@ -59,7 +78,6 @@ class ReprFailDoctest(TerminalRepr):
class DoctestItem(pytest.Item):
def __init__(self, name, parent, runner=None, dtest=None):
super(DoctestItem, self).__init__(name, parent)
self.runner = runner
@@ -70,7 +88,9 @@ class DoctestItem(pytest.Item):
def setup(self):
if self.dtest is not None:
self.fixture_request = _setup_fixtures(self)
globs = dict(getfixture=self.fixture_request.getfuncargvalue)
globs = dict(getfixture=self.fixture_request.getfixturevalue)
for name, value in self.fixture_request.getfixturevalue('doctest_namespace').items():
globs[name] = value
self.dtest.globs.update(globs)
def runtest(self):
@@ -92,7 +112,7 @@ class DoctestItem(pytest.Item):
message = excinfo.type.__name__
reprlocation = ReprFileLocation(filename, lineno, message)
checker = _get_checker()
REPORT_UDIFF = doctest.REPORT_UDIFF
report_choice = _get_report_choice(self.config.getoption("doctestreport"))
if lineno is not None:
lines = doctestfailure.test.docstring.splitlines(False)
# add line numbers to the left of the error message
@@ -108,7 +128,7 @@ class DoctestItem(pytest.Item):
indent = '...'
if excinfo.errisinstance(doctest.DocTestFailure):
lines += checker.output_difference(example,
doctestfailure.got, REPORT_UDIFF).split("\n")
doctestfailure.got, report_choice).split("\n")
else:
inner_excinfo = ExceptionInfo(excinfo.value.exc_info)
lines += ["UNEXPECTED EXCEPTION: %s" %
@@ -143,30 +163,30 @@ def get_optionflags(parent):
flag_acc |= flag_lookup_table[flag]
return flag_acc
class DoctestTextfile(pytest.Module):
obj = None
class DoctestTextfile(DoctestItem, pytest.Module):
def runtest(self):
def collect(self):
import doctest
fixture_request = _setup_fixtures(self)
# inspired by doctest.testfile; ideally we would use it directly,
# but it doesn't support passing a custom checker
text = self.fspath.read()
encoding = self.config.getini("doctest_encoding")
text = self.fspath.read_text(encoding)
filename = str(self.fspath)
name = self.fspath.basename
globs = dict(getfixture=fixture_request.getfuncargvalue)
if '__name__' not in globs:
globs['__name__'] = '__main__'
globs = {'__name__': '__main__'}
optionflags = get_optionflags(self)
runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
checker=_get_checker())
_fix_spoof_python2(runner, encoding)
parser = doctest.DocTestParser()
test = parser.get_doctest(text, globs, name, filename, 0)
_check_all_skipped(test)
runner.run(test)
if test.examples:
yield DoctestItem(test.name, self, runner, test)
def _check_all_skipped(test):
@@ -197,6 +217,10 @@ class DoctestModule(pytest.Module):
optionflags = get_optionflags(self)
runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
checker=_get_checker())
encoding = self.config.getini("doctest_encoding")
_fix_spoof_python2(runner, encoding)
for test in finder.find(module, module.__name__):
if test.examples: # skip empty doctests
yield DoctestItem(test.name, self, runner, test)
@@ -288,3 +312,50 @@ def _get_allow_bytes_flag():
"""
import doctest
return doctest.register_optionflag('ALLOW_BYTES')
def _get_report_choice(key):
"""
This function returns the actual `doctest` module flag value, we want to do it as late as possible to avoid
importing `doctest` and all its dependencies when parsing options, as it adds overhead and breaks tests.
"""
import doctest
return {
DOCTEST_REPORT_CHOICE_UDIFF: doctest.REPORT_UDIFF,
DOCTEST_REPORT_CHOICE_CDIFF: doctest.REPORT_CDIFF,
DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF,
DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE,
DOCTEST_REPORT_CHOICE_NONE: 0,
}[key]
def _fix_spoof_python2(runner, encoding):
"""
Installs a "SpoofOut" into the given DebugRunner so it properly deals with unicode output.
This fixes the problem related in issue #2434.
"""
from _pytest.compat import _PY2
if not _PY2:
return
from doctest import _SpoofOut
class UnicodeSpoof(_SpoofOut):
def getvalue(self):
result = _SpoofOut.getvalue(self)
if encoding:
result = result.decode(encoding)
return result
runner._fakeout = UnicodeSpoof()
@pytest.fixture(scope='session')
def doctest_namespace():
"""
Inject names into the doctest namespace.
"""
return dict()

1120
_pytest/fixtures.py Normal file

File diff suppressed because it is too large Load Diff

44
_pytest/freeze_support.py Normal file
View File

@@ -0,0 +1,44 @@
"""
Provides a function to report all internal modules for using freezing tools
pytest
"""
from __future__ import absolute_import, division, print_function
def freeze_includes():
"""
Returns a list of module names used by py.test that should be
included by cx_freeze.
"""
import py
import _pytest
result = list(_iter_all_modules(py))
result += list(_iter_all_modules(_pytest))
return result
def _iter_all_modules(package, prefix=''):
"""
Iterates over the names of all modules that can be found in the given
package, recursively.
Example:
_iter_all_modules(_pytest) ->
['_pytest.assertion.newinterpret',
'_pytest.capture',
'_pytest.core',
...
]
"""
import os
import pkgutil
if type(package) is not str:
path, prefix = package.__path__[0], package.__name__ + '.'
else:
path = package
for _, name, is_package in pkgutil.iter_modules([path]):
if is_package:
for m in _iter_all_modules(os.path.join(path, name), prefix=name + '.'):
yield prefix + m
else:
yield prefix + name

View File

@@ -1,132 +0,0 @@
""" (deprecated) generate a single-file self-contained version of pytest """
import os
import sys
import pkgutil
import py
import _pytest
def find_toplevel(name):
for syspath in sys.path:
base = py.path.local(syspath)
lib = base/name
if lib.check(dir=1):
return lib
mod = base.join("%s.py" % name)
if mod.check(file=1):
return mod
raise LookupError(name)
def pkgname(toplevel, rootpath, path):
parts = path.parts()[len(rootpath.parts()):]
return '.'.join([toplevel] + [x.purebasename for x in parts])
def pkg_to_mapping(name):
toplevel = find_toplevel(name)
name2src = {}
if toplevel.check(file=1): # module
name2src[toplevel.purebasename] = toplevel.read()
else: # package
for pyfile in toplevel.visit('*.py'):
pkg = pkgname(name, toplevel, pyfile)
name2src[pkg] = pyfile.read()
# with wheels py source code might be not be installed
# and the resulting genscript is useless, just bail out.
assert name2src, "no source code found for %r at %r" %(name, toplevel)
return name2src
def compress_mapping(mapping):
import base64, pickle, zlib
data = pickle.dumps(mapping, 2)
data = zlib.compress(data, 9)
data = base64.encodestring(data)
data = data.decode('ascii')
return data
def compress_packages(names):
mapping = {}
for name in names:
mapping.update(pkg_to_mapping(name))
return compress_mapping(mapping)
def generate_script(entry, packages):
data = compress_packages(packages)
tmpl = py.path.local(__file__).dirpath().join('standalonetemplate.py')
exe = tmpl.read()
exe = exe.replace('@SOURCES@', data)
exe = exe.replace('@ENTRY@', entry)
return exe
def pytest_addoption(parser):
group = parser.getgroup("debugconfig")
group.addoption("--genscript", action="store", default=None,
dest="genscript", metavar="path",
help="create standalone pytest script at given target path.")
def pytest_cmdline_main(config):
import _pytest.config
genscript = config.getvalue("genscript")
if genscript:
tw = _pytest.config.create_terminal_writer(config)
tw.line("WARNING: usage of genscript is deprecated.",
red=True)
deps = ['py', '_pytest', 'pytest'] # pluggy is vendored
if sys.version_info < (2,7):
deps.append("argparse")
tw.line("generated script will run on python2.6-python3.3++")
else:
tw.line("WARNING: generated script will not run on python2.6 "
"due to 'argparse' dependency. Use python2.6 "
"to generate a python2.6 compatible script", red=True)
script = generate_script(
'import pytest; raise SystemExit(pytest.cmdline.main())',
deps,
)
genscript = py.path.local(genscript)
genscript.write(script)
tw.line("generated pytest standalone script: %s" % genscript,
bold=True)
return 0
def pytest_namespace():
return {'freeze_includes': freeze_includes}
def freeze_includes():
"""
Returns a list of module names used by py.test that should be
included by cx_freeze.
"""
result = list(_iter_all_modules(py))
result += list(_iter_all_modules(_pytest))
return result
def _iter_all_modules(package, prefix=''):
"""
Iterates over the names of all modules that can be found in the given
package, recursively.
Example:
_iter_all_modules(_pytest) ->
['_pytest.assertion.newinterpret',
'_pytest.capture',
'_pytest.core',
...
]
"""
if type(package) is not str:
path, prefix = package.__path__[0], package.__name__ + '.'
else:
path = package
for _, name, is_package in pkgutil.iter_modules([path]):
if is_package:
for m in _iter_all_modules(os.path.join(path, name), prefix=name + '.'):
yield prefix + m
else:
yield prefix + name

View File

@@ -1,13 +1,48 @@
""" version info, help messages, tracing configuration. """
from __future__ import absolute_import, division, print_function
import py
import pytest
from _pytest.config import PrintHelp
import os, sys
from argparse import Action
class HelpAction(Action):
"""This is an argparse Action that will raise an exception in
order to skip the rest of the argument parsing when --help is passed.
This prevents argparse from quitting due to missing required arguments
when any are defined, for example by ``pytest_addoption``.
This is similar to the way that the builtin argparse --help option is
implemented by raising SystemExit.
"""
def __init__(self,
option_strings,
dest=None,
default=False,
help=None):
super(HelpAction, self).__init__(
option_strings=option_strings,
dest=dest,
const=True,
default=default,
nargs=0,
help=help)
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, self.const)
# We should only skip the rest of the parsing after preparse is done
if getattr(parser._parser, 'after_preparse', False):
raise PrintHelp
def pytest_addoption(parser):
group = parser.getgroup('debugconfig')
group.addoption('--version', action="store_true",
help="display pytest lib version and import information.")
group._addoption("-h", "--help", action="store_true", dest="help",
group._addoption("-h", "--help", action=HelpAction, dest="help",
help="show help message and configuration info")
group._addoption('-p', action="append", dest="plugins", default = [],
metavar="name",
@@ -20,6 +55,10 @@ def pytest_addoption(parser):
group.addoption('--debug',
action="store_true", dest="debug", default=False,
help="store internal tracing debug information in 'pytestdebug.log'.")
group._addoption(
'-o', '--override-ini', nargs='*', dest="override_ini",
action="append",
help="override config option with option=value style, e.g. `-o xfail_strict=True`.")
@pytest.hookimpl(hookwrapper=True)
@@ -37,12 +76,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):
@@ -67,9 +108,8 @@ def showhelp(config):
tw.write(config._parser.optparser.format_help())
tw.line()
tw.line()
#tw.sep( "=", "config file settings")
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:
@@ -92,8 +132,8 @@ def showhelp(config):
tw.line()
tw.line()
tw.line("to see available markers type: py.test --markers")
tw.line("to see available fixtures type: py.test --fixtures")
tw.line("to see available markers type: pytest --markers")
tw.line("to see available fixtures type: pytest --fixtures")
tw.line("(shown according to specified file_or_dir or current dir "
"if not specified)")

View File

@@ -16,7 +16,9 @@ def pytest_addhooks(pluginmanager):
@hookspec(historic=True)
def pytest_namespace():
"""return dict of name->object to be made globally available in
"""
DEPRECATED: this hook causes direct monkeypatching on pytest, its use is strongly discouraged
return dict of name->object to be made globally available in
the pytest namespace. This hook is called at plugin registration
time.
"""
@@ -34,7 +36,7 @@ def pytest_addoption(parser):
.. note::
This function should be implemented only in plugins or ``conftest.py``
files situated at the tests root directory due to how py.test
files situated at the tests root directory due to how pytest
:ref:`discovers plugins during startup <pluginorder>`.
:arg parser: To add command line options, call
@@ -156,6 +158,13 @@ def pytest_pyfunc_call(pyfuncitem):
def pytest_generate_tests(metafunc):
""" generate (multiple) parametrized calls to a test function."""
@hookspec(firstresult=True)
def pytest_make_parametrize_id(config, val, argname):
"""Return a user-friendly string representation of the given ``val`` that will be used
by @pytest.mark.parametrize calls. Return None if the hook doesn't know about ``val``.
The parameter name is available as ``argname``, if required.
"""
# -------------------------------------------------------------------------
# generic runtest related hooks
# -------------------------------------------------------------------------
@@ -204,7 +213,7 @@ def pytest_runtest_teardown(item, nextitem):
@hookspec(firstresult=True)
def pytest_runtest_makereport(item, call):
""" return a :py:class:`_pytest.runner.TestReport` object
for the given :py:class:`pytest.Item` and
for the given :py:class:`pytest.Item <_pytest.main.Item>` and
:py:class:`_pytest.runner.CallInfo`.
"""
@@ -212,6 +221,19 @@ def pytest_runtest_logreport(report):
""" process a test setup/call/teardown report relating to
the respective phase of executing a test. """
# -------------------------------------------------------------------------
# Fixture related hooks
# -------------------------------------------------------------------------
@hookspec(firstresult=True)
def pytest_fixture_setup(fixturedef, request):
""" performs fixture setup execution. """
def pytest_fixture_post_finalizer(fixturedef):
""" called after fixture teardown, but before the cache is cleared so
the fixture result cache ``fixturedef.cached_result`` can
still be accessed."""
# -------------------------------------------------------------------------
# test session related hooks
# -------------------------------------------------------------------------
@@ -227,7 +249,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):
@@ -236,7 +258,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.
"""
# -------------------------------------------------------------------------
@@ -244,13 +266,20 @@ 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):
""" return result-category, shortletter and verbose word for reporting."""
def pytest_terminal_summary(terminalreporter):
def pytest_terminal_summary(terminalreporter, exitstatus):
""" add additional section in terminal summary reporting. """

View File

@@ -4,16 +4,20 @@
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
Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
"""
from __future__ import absolute_import, division, print_function
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 +31,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
@@ -102,6 +107,8 @@ class _NodeReporter(object):
}
if testreport.location[1] is not None:
attrs["line"] = testreport.location[1]
if hasattr(testreport, "url"):
attrs["url"] = testreport.url
self.attrs = attrs
def to_xml(self):
@@ -116,19 +123,15 @@ 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'):
allcontent = ""
for name, content in report.get_sections("Captured std%s" %
capname):
allcontent += content
if allcontent:
content = getattr(report, 'capstd' + capname)
if content:
tag = getattr(Junit, 'system-' + capname)
self.append(tag(bin_xml_escape(allcontent)))
self.append(tag(bin_xml_escape(content)))
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)
@@ -147,7 +150,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)
@@ -159,9 +161,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"):
@@ -176,7 +181,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)
@@ -186,8 +191,8 @@ class _NodeReporter(object):
@pytest.fixture
def record_xml_property(request):
"""Fixture that adds extra xml properties to the tag for the calling test.
The fixture is callable with (name, value), with value being automatically
"""Add extra xml properties to the tag for the calling test.
The fixture is callable with ``(name, value)``, with value being automatically
xml-encoded.
"""
request.node.warn(
@@ -212,6 +217,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(
@@ -220,13 +226,14 @@ def pytest_addoption(parser):
metavar="str",
default=None,
help="prepend prefix to classnames in junit-xml output")
parser.addini("junit_suite_name", "Test suite name for JUnit report", default="pytest")
def pytest_configure(config):
xmlpath = config.option.xmlpath
# prevent opening xmllog on slave nodes (xdist)
if xmlpath and not hasattr(config, 'slaveinput'):
config._xml = LogXML(xmlpath, config.option.junitprefix)
config._xml = LogXML(xmlpath, config.option.junitprefix, config.getini("junit_suite_name"))
config.pluginmanager.register(config._xml)
@@ -253,10 +260,11 @@ def mangle_test_address(address):
class LogXML(object):
def __init__(self, logfile, prefix):
def __init__(self, logfile, prefix, suite_name="pytest"):
logfile = os.path.expanduser(os.path.expandvars(logfile))
self.logfile = os.path.normpath(os.path.abspath(logfile))
self.prefix = prefix
self.suite_name = suite_name
self.stats = dict.fromkeys([
'error',
'passed',
@@ -265,6 +273,10 @@ class LogXML(object):
], 0)
self.node_reporters = {} # nodeid -> _NodeReporter
self.node_reporters_ordered = []
self.global_properties = []
# List of reports that failed on call but teardown is pending.
self.open_reports = []
self.cnt_double_fail_tests = 0
def finalize(self, report):
nodeid = getattr(report, 'nodeid', report)
@@ -284,9 +296,12 @@ class LogXML(object):
if key in self.node_reporters:
# TODO: breasks for --dist=each
return self.node_reporters[key]
reporter = _NodeReporter(nodeid, self)
self.node_reporters[key] = reporter
self.node_reporters_ordered.append(reporter)
return reporter
def add_stats(self, key):
@@ -321,14 +336,33 @@ class LogXML(object):
-> teardown node2
-> teardown node1
"""
close_report = None
if report.passed:
if report.when == "call": # ignore setup/teardown
reporter = self._opentestcase(report)
reporter.append_pass(report)
elif report.failed:
if report.when == "teardown":
# The following vars are needed when xdist plugin is used
report_wid = getattr(report, "worker_id", None)
report_ii = getattr(report, "item_index", None)
close_report = next(
(rep for rep in self.open_reports
if (rep.nodeid == report.nodeid and
getattr(rep, "item_index", None) == report_ii and
getattr(rep, "worker_id", None) == report_wid
)
), None)
if close_report:
# We need to open new testcase in case we have failure in
# call and error in teardown in order to follow junit
# schema
self.finalize(close_report)
self.cnt_double_fail_tests += 1
reporter = self._opentestcase(report)
if report.when == "call":
reporter.append_failure(report)
self.open_reports.append(report)
else:
reporter.append_error(report)
elif report.skipped:
@@ -336,7 +370,20 @@ 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)
report_wid = getattr(report, "worker_id", None)
report_ii = getattr(report, "item_index", None)
close_report = next(
(rep for rep in self.open_reports
if (rep.nodeid == report.nodeid and
getattr(rep, "item_index", None) == report_ii and
getattr(rep, "worker_id", None) == report_wid
)
), None)
if close_report:
self.open_reports.remove(close_report)
def update_testcase_duration(self, report):
"""accumulates total duration for nodeid from given report and updates
@@ -369,12 +416,15 @@ class LogXML(object):
suite_stop_time = time.time()
suite_time_delta = suite_stop_time - self.suite_start_time
numtests = self.stats['passed'] + self.stats['failure'] + self.stats['skipped']
numtests = (self.stats['passed'] + self.stats['failure'] +
self.stats['skipped'] + self.stats['error'] -
self.cnt_double_fail_tests)
logfile.write('<?xml version="1.0" encoding="utf-8"?>')
logfile.write(Junit.testsuite(
self._get_global_properties_node(),
[x.to_xml() for x in self.node_reporters_ordered],
name="pytest",
name=self.suite_name,
errors=self.stats['error'],
failures=self.stats['failure'],
skips=self.stats['skipped'],
@@ -385,3 +435,18 @@ class LogXML(object):
def pytest_terminal_summary(self, terminalreporter):
terminalreporter.write_sep("-",
"generated xml file: %s" % (self.logfile))
def add_global_property(self, name, value):
self.global_properties.append((str(name), bin_xml_escape(value)))
def _get_global_properties_node(self):
"""Return a Junit node containing custom properties, if any.
"""
if self.global_properties:
return Junit.properties(
[
Junit.property(name=name, value=value)
for name, value in self.global_properties
]
)
return ''

View File

@@ -1,19 +1,20 @@
""" core implementation of testing process: init, session, runtest loop. """
import imp
from __future__ import absolute_import, division, print_function
import functools
import os
import re
import sys
import _pytest
import _pytest._code
import py
import pytest
try:
from collections import MutableMapping as MappingMixin
except ImportError:
from UserDict import DictMixin as MappingMixin
from _pytest.runner import collect_one_node
from _pytest.config import directory_arg, UsageError, hookimpl
from _pytest.runner import collect_one_node, exit
tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
@@ -25,11 +26,10 @@ EXIT_INTERNALERROR = 3
EXIT_USAGEERROR = 4
EXIT_NOTESTSCOLLECTED = 5
name_re = re.compile("^[a-zA-Z_]\w*$")
def pytest_addoption(parser):
parser.addini("norecursedirs", "directory patterns to avoid for recursion",
type="args", default=['.*', 'CVS', '_darcs', '{arch}', '*.egg'])
type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv'])
parser.addini("testpaths", "directories to search for tests when no files or directories are given in the command line.",
type="args", default=[])
#parser.addini("dirpatterns",
@@ -38,8 +38,8 @@ def pytest_addoption(parser):
# "**/test_*.py", "**/*_test.py"]
#)
group = parser.getgroup("general", "running and selection options")
group._addoption('-x', '--exitfirst', action="store_true", default=False,
dest="exitfirst",
group._addoption('-x', '--exitfirst', action="store_const",
dest="maxfail", const=1,
help="exit instantly on first error or failed test."),
group._addoption('--maxfail', metavar="num",
action="store", type=int, dest="maxfail", default=0,
@@ -48,6 +48,9 @@ def pytest_addoption(parser):
help="run pytest in strict mode, warnings become errors.")
group._addoption("-c", metavar="file", type=str, dest="inifilename",
help="load configuration from `file` instead of trying to locate one of the implicit configuration files.")
group._addoption("--continue-on-collection-errors", action="store_true",
default=False, dest="continue_on_collection_errors",
help="Force test execution even if collection errors occur.")
group = parser.getgroup("collect", "collection")
group.addoption('--collectonly', '--collect-only', action="store_true",
@@ -59,11 +62,14 @@ 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,
help="Don't load any conftest.py files.")
group.addoption('--keepduplicates', '--keep-duplicates', action="store_true",
dest="keepduplicates", default=False,
help="Keep duplicate tests.")
group = parser.getgroup("debugconfig",
"test session debugging and configuration")
@@ -71,14 +77,19 @@ def pytest_addoption(parser):
help="base temporary directory for this test run.")
def pytest_namespace():
collect = dict(Item=Item, Collector=Collector, File=File, Session=Session)
return dict(collect=collect)
"""keeping this one works around a deeper startup issue in pytest
i tried to find it for a while but the amount of time turned unsustainable,
so i put a hack in to revisit later
"""
return {}
def pytest_configure(config):
pytest.config = config # compatibiltiy
if config.option.exitfirst:
config.option.maxfail = 1
__import__('pytest').config = config # compatibiltiy
def wrap_session(config, doit):
"""Skeleton command line program"""
@@ -92,10 +103,13 @@ def wrap_session(config, doit):
config.hook.pytest_sessionstart(session=session)
initstate = 2
session.exitstatus = doit(config, session) or 0
except pytest.UsageError:
except UsageError:
raise
except KeyboardInterrupt:
excinfo = _pytest._code.ExceptionInfo()
if initstate < 2 and isinstance(excinfo.value, exit.Exception):
sys.stderr.write('{0}: {1}\n'.format(
excinfo.typename, excinfo.value.msg))
config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
session.exitstatus = EXIT_INTERRUPTED
except:
@@ -115,9 +129,11 @@ def wrap_session(config, doit):
config._ensure_unconfigure()
return session.exitstatus
def pytest_cmdline_main(config):
return wrap_session(config, _main)
def _main(config, session):
""" default command line protocol for initialization, session,
running tests and reporting. """
@@ -129,29 +145,28 @@ def _main(config, session):
elif session.testscollected == 0:
return EXIT_NOTESTSCOLLECTED
def pytest_collection(session):
return session.perform_collect()
def pytest_runtestloop(session):
if (session.testsfailed and
not session.config.option.continue_on_collection_errors):
raise session.Interrupted(
"%d errors during collection" % session.testsfailed)
if session.config.option.collectonly:
return True
def getnextitem(i):
# this is a function to avoid python2
# keeping sys.exc_info set when calling into a test
# python2 keeps sys.exc_info till the frame is left
try:
return session.items[i+1]
except IndexError:
return None
for i, item in enumerate(session.items):
nextitem = getnextitem(i)
nextitem = session.items[i+1] if i+1 < len(session.items) else None
item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
if session.shouldstop:
raise session.Interrupted(session.shouldstop)
return True
def pytest_ignore_collect(path, config):
p = path.dirpath()
ignore_paths = config._getconftest_pathlist("collect_ignore", path=p)
@@ -159,7 +174,21 @@ def pytest_ignore_collect(path, config):
excludeopt = config.getoption("ignore")
if excludeopt:
ignore_paths.extend([py.path.local(x) for x in excludeopt])
return path in ignore_paths
if path in ignore_paths:
return True
# Skip duplicate paths.
keepduplicates = config.getoption("keepduplicates")
duplicate_paths = config.pluginmanager._duplicatepaths
if not keepduplicates:
if path in duplicate_paths:
return True
else:
duplicate_paths.add(path)
return False
class FSHookProxy:
def __init__(self, fspath, pm, remove_mods):
@@ -172,12 +201,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(__import__('pytest'), self.name)
return property(fget)
class NodeKeywords(MappingMixin):
def __init__(self, node):
@@ -249,19 +288,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(__import__('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):
@@ -275,9 +318,6 @@ class Node(object):
fslocation = getattr(self, "location", None)
if fslocation is None:
fslocation = getattr(self, "fspath", None)
else:
fslocation = "%s:%s" % fslocation[:2]
self.ihook.pytest_logwarning.call_historic(kwargs=dict(
code=code, message=message,
nodeid=self.nodeid, fslocation=fslocation))
@@ -338,9 +378,9 @@ class Node(object):
``marker`` can be a string or pytest.mark.* instance.
"""
from _pytest.mark import MarkDecorator
from _pytest.mark import MarkDecorator, MARK_GEN
if isinstance(marker, py.builtin._basestring):
marker = MarkDecorator(marker)
marker = getattr(MARK_GEN, marker)
elif not isinstance(marker, MarkDecorator):
raise ValueError("is not a string or pytest.mark.* Marker")
self.keywords[marker.name] = marker
@@ -392,7 +432,10 @@ class Node(object):
if self.config.option.fulltrace:
style="long"
else:
tb = _pytest._code.Traceback([excinfo.traceback[-1]])
self._prunetraceback(excinfo)
if len(excinfo.traceback) == 0:
excinfo.traceback = tb
tbfilter = False # prunetraceback already does it
if style == "auto":
style = "long"
@@ -403,7 +446,13 @@ class Node(object):
else:
style = "long"
return excinfo.getrepr(funcargs=True,
try:
os.getcwd()
abspath = False
except OSError:
abspath = True
return excinfo.getrepr(funcargs=True, abspath=abspath,
showlocals=self.config.option.showlocals,
style=style, tbfilter=tbfilter)
@@ -430,10 +479,6 @@ class Collector(Node):
return str(exc.args[0])
return self._repr_failure_py(excinfo, style="short")
def _memocollect(self):
""" internal helper method to cache results of calling collect(). """
return self._memoizedcall('_collected', lambda: list(self.collect()))
def _prunetraceback(self, excinfo):
if hasattr(self, 'fspath'):
traceback = excinfo.traceback
@@ -510,7 +555,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
@@ -522,12 +566,12 @@ class Session(FSCollector):
def _makeid(self):
return ""
@pytest.hookimpl(tryfirst=True)
@hookimpl(tryfirst=True)
def pytest_collectstart(self):
if self.shouldstop:
raise self.Interrupted(self.shouldstop)
@pytest.hookimpl(tryfirst=True)
@hookimpl(tryfirst=True)
def pytest_runtest_logreport(self, report):
if report.failed and not hasattr(report, 'wasxfail'):
self.testsfailed += 1
@@ -541,28 +585,24 @@ 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
try:
items = self._perform_collect(args, genitems)
self.config.pluginmanager.check_pending()
hook.pytest_collection_modifyitems(session=self,
config=self.config, items=items)
finally:
@@ -591,8 +631,8 @@ class Session(FSCollector):
for arg, exc in self._notfound:
line = "(no name %r in any of %r)" % (arg, exc.args[0])
errors.append("not found: %s\n%s" % (arg, line))
#XXX: test this
raise pytest.UsageError(*errors)
# XXX: test this
raise UsageError(*errors)
if not genitems:
return rep.result
else:
@@ -620,7 +660,7 @@ class Session(FSCollector):
names = self._parsearg(arg)
path = names.pop(0)
if path.check(dir=1):
assert not names, "invalid arg %r" %(arg,)
assert not names, "invalid arg %r" % (arg,)
for path in path.visit(fil=lambda x: x.check(file=1),
rec=self._recurse, bf=True, sort=True):
for x in self._collectfile(path):
@@ -649,44 +689,41 @@ class Session(FSCollector):
return True
def _tryconvertpyarg(self, x):
mod = None
path = [os.path.abspath('.')] + sys.path
for name in x.split('.'):
# ignore anything that's not a proper name here
# else something like --pyargs will mess up '.'
# since imp.find_module will actually sometimes work for it
# but it's supposed to be considered a filesystem path
# not a package
if name_re.match(name) is None:
return x
try:
fd, mod, type_ = imp.find_module(name, path)
except ImportError:
return x
else:
if fd is not None:
fd.close()
"""Convert a dotted module name to path.
if type_[2] != imp.PKG_DIRECTORY:
path = [os.path.dirname(mod)]
else:
path = [mod]
return mod
"""
import pkgutil
try:
loader = pkgutil.find_loader(x)
except ImportError:
return x
if loader is None:
return x
# This method is sometimes invoked when AssertionRewritingHook, which
# does not define a get_filename method, is already in place:
try:
path = loader.get_filename(x)
except AttributeError:
# Retrieve path from AssertionRewritingHook:
path = loader.modules[x][0].co_filename
if loader.is_package(x):
path = os.path.dirname(path)
return path
def _parsearg(self, arg):
""" return (fspath, names) tuple after checking the file exists. """
arg = str(arg)
if self.config.option.pyargs:
arg = self._tryconvertpyarg(arg)
parts = str(arg).split("::")
if self.config.option.pyargs:
parts[0] = self._tryconvertpyarg(parts[0])
relpath = parts[0].replace("/", os.sep)
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 UsageError(
"file or package not found: " + arg +
" (missing __init__.py?)")
else:
msg = "file not found: "
raise pytest.UsageError(msg + arg)
raise UsageError("file not found: " + arg)
parts[0] = path
return parts
@@ -709,11 +746,11 @@ class Session(FSCollector):
nextnames = names[1:]
resultnodes = []
for node in matching:
if isinstance(node, pytest.Item):
if isinstance(node, Item):
if not names:
resultnodes.append(node)
continue
assert isinstance(node, pytest.Collector)
assert isinstance(node, Collector)
rep = collect_one_node(node)
if rep.passed:
has_matched = False
@@ -731,11 +768,11 @@ class Session(FSCollector):
def genitems(self, node):
self.trace("genitems", node)
if isinstance(node, pytest.Item):
if isinstance(node, Item):
node.ihook.pytest_itemcollected(item=node)
yield node
else:
assert isinstance(node, pytest.Collector)
assert isinstance(node, Collector)
rep = collect_one_node(node)
if rep.passed:
for subnode in rep.result:

View File

@@ -1,5 +1,64 @@
""" generic mechanism for marking and selecting python functions. """
from __future__ import absolute_import, division, print_function
import inspect
from collections import namedtuple
from operator import attrgetter
from .compat import imap
def alias(name):
return property(attrgetter(name), doc='alias for ' + name)
class ParameterSet(namedtuple('ParameterSet', 'values, marks, id')):
@classmethod
def param(cls, *values, **kw):
marks = kw.pop('marks', ())
if isinstance(marks, MarkDecorator):
marks = marks,
else:
assert isinstance(marks, (tuple, list, set))
def param_extract_id(id=None):
return id
id = param_extract_id(**kw)
return cls(values, marks, id)
@classmethod
def extract_from(cls, parameterset, legacy_force_tuple=False):
"""
:param parameterset:
a legacy style parameterset that may or may not be a tuple,
and may or may not be wrapped into a mess of mark objects
:param legacy_force_tuple:
enforce tuple wrapping so single argument tuple values
don't get decomposed and break tests
"""
if isinstance(parameterset, cls):
return parameterset
if not isinstance(parameterset, MarkDecorator) and legacy_force_tuple:
return cls.param(parameterset)
newmarks = []
argval = parameterset
while isinstance(argval, MarkDecorator):
newmarks.append(MarkDecorator(Mark(
argval.markname, argval.args[:-1], argval.kwargs)))
argval = argval.args[-1]
assert not isinstance(argval, ParameterSet)
if legacy_force_tuple:
argval = argval,
return cls(argval, marks=newmarks, id=None)
@property
def deprecated_arg_dict(self):
return dict((mark.name, mark) for mark in self.marks)
class MarkerError(Exception):
@@ -7,8 +66,8 @@ class MarkerError(Exception):
"""Error in use of a pytest marker/attribute."""
def pytest_namespace():
return {'mark': MarkGenerator()}
def param(*values, **kw):
return ParameterSet.param(*values, **kw)
def pytest_addoption(parser):
@@ -19,7 +78,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 +113,8 @@ def pytest_cmdline_main(config):
tw.line()
config._ensure_unconfigure()
return 0
pytest_cmdline_main.tryfirst = True
@@ -64,7 +125,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
@@ -160,9 +221,13 @@ def matchkeyword(colitem, keywordexpr):
def pytest_configure(config):
import pytest
config._old_mark_config = MARK_GEN._config
if config.option.strict:
pytest.mark._config = config
MARK_GEN._config = config
def pytest_unconfigure(config):
MARK_GEN._config = getattr(config, '_old_mark_config', None)
class MarkGenerator:
@@ -176,13 +241,15 @@ class MarkGenerator:
will set a 'slowtest' :class:`MarkInfo` object
on the ``test_function`` object. """
_config = None
def __getattr__(self, name):
if name[0] == "_":
raise AttributeError("Marker name must NOT start with underscore")
if hasattr(self, '_config'):
if self._config is not None:
self._check(name)
return MarkDecorator(name)
return MarkDecorator(Mark(name, (), {}))
def _check(self, name):
try:
@@ -198,6 +265,7 @@ class MarkGenerator:
if name not in self._markers:
raise AttributeError("%r not a registered marker" % (name,))
def istestfunc(func):
return hasattr(func, "__call__") and \
getattr(func, "__name__", "<lambda>") != "<lambda>"
@@ -235,19 +303,23 @@ class MarkDecorator:
additional keyword or positional arguments.
"""
def __init__(self, name, args=None, kwargs=None):
self.name = name
self.args = args or ()
self.kwargs = kwargs or {}
def __init__(self, mark):
assert isinstance(mark, Mark), repr(mark)
self.mark = mark
name = alias('mark.name')
args = alias('mark.args')
kwargs = alias('mark.kwargs')
@property
def markname(self):
return self.name # for backward-compat (2.4.1 had this attr)
def __eq__(self, other):
return self.mark == other.mark
def __repr__(self):
d = self.__dict__.copy()
name = d.pop('name')
return "<MarkDecorator %r %r>" % (name, d)
return "<MarkDecorator %r>" % (self.mark,)
def __call__(self, *args, **kwargs):
""" if passed a single callable argument: decorate it with mark info.
@@ -270,42 +342,50 @@ class MarkDecorator:
else:
holder = getattr(func, self.name, None)
if holder is None:
holder = MarkInfo(
self.name, self.args, self.kwargs
)
holder = MarkInfo(self.mark)
setattr(func, self.name, holder)
else:
holder.add(self.args, self.kwargs)
holder.add_mark(self.mark)
return func
kw = self.kwargs.copy()
kw.update(kwargs)
args = self.args + args
return self.__class__(self.name, args=args, kwargs=kw)
mark = Mark(self.name, args, kwargs)
return self.__class__(self.mark.combined_with(mark))
class MarkInfo:
class Mark(namedtuple('Mark', 'name, args, kwargs')):
def combined_with(self, other):
assert self.name == other.name
return Mark(
self.name, self.args + other.args,
dict(self.kwargs, **other.kwargs))
class MarkInfo(object):
""" Marking object created by :class:`MarkDecorator` instances. """
def __init__(self, name, args, kwargs):
#: name of attribute
self.name = name
#: positional argument list, empty if none specified
self.args = args
#: keyword argument dictionary, empty if nothing specified
self.kwargs = kwargs.copy()
self._arglist = [(args, kwargs.copy())]
def __init__(self, mark):
assert isinstance(mark, Mark), repr(mark)
self.combined = mark
self._marks = [mark]
name = alias('combined.name')
args = alias('combined.args')
kwargs = alias('combined.kwargs')
def __repr__(self):
return "<MarkInfo %r args=%r kwargs=%r>" % (
self.name, self.args, self.kwargs
)
return "<MarkInfo {0!r}>".format(self.combined)
def add(self, args, kwargs):
def add_mark(self, mark):
""" add a MarkInfo with the given args and kwargs. """
self._arglist.append((args, kwargs))
self.args += args
self.kwargs.update(kwargs)
self._marks.append(mark)
self.combined = self.combined.combined_with(mark)
def __iter__(self):
""" yield MarkInfo objects each relating to a marking-call. """
for args, kwargs in self._arglist:
yield MarkInfo(self.name, args, kwargs)
return imap(MarkInfo, self._marks)
MARK_GEN = MarkGenerator()

View File

@@ -1,15 +1,19 @@
""" monkeypatching and mocking functionality. """
from __future__ import absolute_import, division, print_function
import os, sys
import os
import sys
import re
from py.builtin import _basestring
from _pytest.fixtures import fixture
RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$")
def pytest_funcarg__monkeypatch(request):
"""The returned ``monkeypatch`` funcarg provides these
@fixture
def monkeypatch():
"""The returned ``monkeypatch`` fixture provides these
helper methods to modify objects, dictionaries or os.environ::
monkeypatch.setattr(obj, name, value, raising=True)
@@ -22,13 +26,13 @@ def pytest_funcarg__monkeypatch(request):
monkeypatch.chdir(path)
All modifications will be undone after the requesting
test function has finished. The ``raising``
test function or fixture has finished. The ``raising``
parameter determines if a KeyError or AttributeError
will be raised if the set/deletion operation has no target.
"""
mpatch = monkeypatch()
request.addfinalizer(mpatch.undo)
return mpatch
mpatch = MonkeyPatch()
yield mpatch
mpatch.undo()
def resolve(name):
@@ -93,8 +97,9 @@ class Notset:
notset = Notset()
class monkeypatch:
""" Object keeping a record of setattr/item/env/syspath changes. """
class MonkeyPatch:
""" Object returned by the ``monkeypatch`` fixture keeping a record of setattr/item/env/syspath changes.
"""
def __init__(self):
self._setattr = []
@@ -220,10 +225,10 @@ class monkeypatch:
""" Undo previous changes. This call consumes the
undo stack. Calling it a second time has no effect unless
you do more monkeypatching after the undo call.
There is generally no need to call `undo()`, since it is
called automatically during tear-down.
Note that the same `monkeypatch` fixture is used across a
single test function invocation. If `monkeypatch` is used both by
the test function itself and one of the test fixtures,

View File

@@ -1,10 +1,11 @@
""" run test suites written for nose. """
from __future__ import absolute_import, division, print_function
import sys
import py
import pytest
from _pytest import unittest
from _pytest import unittest, runner, python
from _pytest.config import hookimpl
def get_skip_exceptions():
@@ -19,19 +20,19 @@ def get_skip_exceptions():
def pytest_runtest_makereport(item, call):
if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()):
# let's substitute the excinfo with a pytest.skip one
call2 = call.__class__(lambda:
pytest.skip(str(call.excinfo.value)), call.when)
call2 = call.__class__(
lambda: runner.skip(str(call.excinfo.value)), call.when)
call.excinfo = call2.excinfo
@pytest.hookimpl(trylast=True)
@hookimpl(trylast=True)
def pytest_runtest_setup(item):
if is_potential_nosetest(item):
if isinstance(item.parent, pytest.Generator):
if isinstance(item.parent, python.Generator):
gen = item.parent
if not hasattr(gen, '_nosegensetup'):
call_optional(gen.obj, 'setup')
if isinstance(gen.parent, pytest.Instance):
if isinstance(gen.parent, python.Instance):
call_optional(gen.parent.obj, 'setup')
gen._nosegensetup = True
if not call_optional(item.obj, 'setup'):
@@ -50,14 +51,14 @@ def teardown_nose(item):
def pytest_make_collect_report(collector):
if isinstance(collector, pytest.Generator):
if isinstance(collector, python.Generator):
call_optional(collector.obj, 'setup')
def is_potential_nosetest(item):
# extra check needed since we do not do nose style setup/teardown
# on direct unittest style classes
return isinstance(item, pytest.Function) and \
return isinstance(item, python.Function) and \
not isinstance(item, unittest.TestCaseFunction)

View File

@@ -1,4 +1,6 @@
""" submit failure or test session information to a pastebin service. """
from __future__ import absolute_import, division, print_function
import pytest
import sys
import tempfile
@@ -11,6 +13,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 +26,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 +51,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 +79,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

@@ -1,4 +1,6 @@
""" (disabled by default) support for testing pytest and pytest plugins. """
from __future__ import absolute_import, division, print_function
import codecs
import gc
import os
@@ -10,12 +12,14 @@ import time
import traceback
from fnmatch import fnmatch
from py.builtin import print_
from weakref import WeakKeyDictionary
from _pytest.capture import MultiCapture, SysCapture
from _pytest._code import Source
import py
import pytest
from _pytest.main import Session, EXIT_OK
from _pytest.assertion.rewrite import AssertionRewritingHook
def pytest_addoption(parser):
@@ -84,7 +88,7 @@ class LsofFdLeakChecker(object):
return True
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_item(self, item):
def pytest_runtest_protocol(self, item):
lines1 = self.get_open_files()
yield
if hasattr(sys, "pypy_version_info"):
@@ -103,7 +107,8 @@ class LsofFdLeakChecker(object):
error.extend([str(f) for f in lines2])
error.append(error[0])
error.append("*** function %s:%s: %s " % item.location)
pytest.fail("\n".join(error), pytrace=False)
error.append("See issue #2366")
item.warn('', "\n".join(error))
# XXX copied from execnet's conftest.py - needs to be merged
@@ -123,15 +128,18 @@ def getexecutable(name, cache={}):
except KeyError:
executable = py.path.local.sysfind(name)
if executable:
import subprocess
popen = subprocess.Popen([str(executable), "--version"],
universal_newlines=True, stderr=subprocess.PIPE)
out, err = popen.communicate()
if name == "jython":
import subprocess
popen = subprocess.Popen([str(executable), "--version"],
universal_newlines=True, stderr=subprocess.PIPE)
out, err = popen.communicate()
if not err or "2.5" not in err:
executable = None
if "2.5.2" in err:
executable = None # http://bugs.jython.org/issue1790
elif popen.returncode != 0:
# Handle pyenv's 127.
executable = None
cache[name] = executable
return executable
@@ -222,15 +230,15 @@ class HookRecorder:
name, check = entries.pop(0)
for ind, call in enumerate(self.calls[i:]):
if call._name == name:
print_("NAMEMATCH", name, call)
print("NAMEMATCH", name, call)
if eval(check, backlocals, call.__dict__):
print_("CHECKERMATCH", repr(check), "->", call)
print("CHECKERMATCH", repr(check), "->", call)
else:
print_("NOCHECKERMATCH", repr(check), "-", call)
print("NOCHECKERMATCH", repr(check), "-", call)
continue
i += ind + 1
break
print_("NONAMEMATCH", name, "with", call)
print("NONAMEMATCH", name, "with", call)
else:
pytest.fail("could not find %r check %r" % (name, check))
@@ -318,7 +326,8 @@ def linecomp(request):
return LineComp()
def pytest_funcarg__LineMatcher(request):
@pytest.fixture(name='LineMatcher')
def LineMatcher_fixture(request):
return LineMatcher
@@ -327,7 +336,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.
@@ -362,6 +371,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
@@ -374,10 +384,10 @@ class RunResult:
class Testdir:
"""Temporary test directory with tools to test/run py.test itself.
"""Temporary test directory with tools to test/run pytest itself.
This is based on the ``tmpdir`` fixture but provides a number of
methods which aid with testing py.test itself. Unless
methods which aid with testing pytest itself. Unless
:py:meth:`chdir` is used all methods will use :py:attr:`tmpdir` as
current working directory.
@@ -396,6 +406,7 @@ class Testdir:
def __init__(self, request, tmpdir_factory):
self.request = request
self._mod_collections = WeakKeyDictionary()
# XXX remove duplication with tmpdir plugin
basetmp = tmpdir_factory.ensuretemp("testdir")
name = request.function.__name__
@@ -441,9 +452,10 @@ 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":
# some zope modules used by twisted-related tests keeps internal
# state and can't be deleted; we had some trouble in the past
# with zope.interface for example
if not name.startswith("zope"):
del sys.modules[name]
def make_hook_recorder(self, pluginmanager):
@@ -463,7 +475,7 @@ class Testdir:
if not hasattr(self, '_olddir'):
self._olddir = old
def _makefile(self, ext, args, kwargs):
def _makefile(self, ext, args, kwargs, encoding="utf-8"):
items = list(kwargs.items())
if args:
source = py.builtin._totext("\n").join(
@@ -473,14 +485,17 @@ 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"
content = source.strip().encode(encoding) # + "\n"
#content = content.rstrip() + "\n"
p.write(content, "wb")
if ret is None:
@@ -557,7 +572,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.
"""
@@ -588,7 +603,7 @@ class Testdir:
"""Return the collection node of a file.
This is like :py:meth:`getnode` but uses
:py:meth:`parseconfigure` to create the (configured) py.test
:py:meth:`parseconfigure` to create the (configured) pytest
Config instance.
:param path: A :py:class:`py.path.local` instance of the file.
@@ -652,11 +667,11 @@ 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
py.test inside the test process itself like
pytest inside the test process itself like
:py:meth:`inline_run`. However the return value is a tuple of
the collection items and a :py:class:`HookRecorder` instance.
@@ -669,7 +684,7 @@ class Testdir:
"""Run ``pytest.main()`` in-process, returning a HookRecorder.
This runs the :py:func:`pytest.main` function to run all of
py.test inside the test process itself. This means it can
pytest inside the test process itself. This means it can
return a :py:class:`HookRecorder` instance which gives more
detailed results from then run then can be done by matching
stdout/stderr from :py:meth:`runpytest`.
@@ -681,9 +696,21 @@ class Testdir:
``pytest.main()`` instance should use.
:return: A :py:class:`HookRecorder` instance.
"""
# When running py.test inline any plugins active in the main
# test process are already imported. So this disables the
# 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))
@@ -713,19 +740,24 @@ class Testdir:
if kwargs.get("syspathinsert"):
self.syspathinsert()
now = time.time()
capture = py.io.StdCapture()
capture = MultiCapture(Capture=SysCapture)
capture.start_capturing()
try:
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:
out, err = capture.reset()
out, err = capture.readouterr()
capture.stop_capturing()
sys.stdout.write(out)
sys.stderr.write(err)
@@ -755,9 +787,9 @@ class Testdir:
return args
def parseconfig(self, *args):
"""Return a new py.test Config instance from given commandline args.
"""Return a new pytest Config instance from given commandline args.
This invokes the py.test bootstrapping code in _pytest.config
This invokes the pytest bootstrapping code in _pytest.config
to create a new :py:class:`_pytest.core.PluginManager` and
call the pytest_cmdline_parse hook to create new
:py:class:`_pytest.config.Config` instance.
@@ -777,7 +809,7 @@ class Testdir:
return config
def parseconfigure(self, *args):
"""Return a new py.test configured Config instance.
"""Return a new pytest configured Config instance.
This returns a new :py:class:`_pytest.config.Config` instance
like :py:meth:`parseconfig`, but also calls the
@@ -792,7 +824,7 @@ class Testdir:
def getitem(self, source, funcname="test_func"):
"""Return the test item for a test function.
This writes the source to a python file and runs py.test's
This writes the source to a python file and runs pytest's
collection on the resulting module, returning the test item
for the requested function name.
@@ -812,7 +844,7 @@ class Testdir:
def getitems(self, source):
"""Return all test items collected from the module.
This writes the source to a python file and runs py.test's
This writes the source to a python file and runs pytest's
collection on the resulting module, returning all test items
contained within.
@@ -824,7 +856,7 @@ class Testdir:
"""Return the module collection node for ``source``.
This writes ``source`` to a file using :py:meth:`makepyfile`
and then runs the py.test collection on it, returning the
and then runs the pytest collection on it, returning the
collection node for the test module.
:param source: The source code of the module to collect.
@@ -833,7 +865,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()}
@@ -842,6 +874,7 @@ class Testdir:
self.makepyfile(__init__ = "#")
self.config = config = self.parseconfigure(path, *configargs)
node = self.getnode(config, path)
return node
def collect_by_name(self, modcol, name):
@@ -856,7 +889,9 @@ class Testdir:
:param name: The name of the node to return.
"""
for colitem in modcol._memocollect():
if modcol not in self._mod_collections:
self._mod_collections[modcol] = list(modcol.collect())
for colitem in self._mod_collections[modcol]:
if colitem.name == name:
return colitem
@@ -891,8 +926,8 @@ class Testdir:
cmdargs = [str(x) for x in cmdargs]
p1 = self.tmpdir.join("stdout")
p2 = self.tmpdir.join("stderr")
print_("running:", ' '.join(cmdargs))
print_(" in:", str(py.path.local()))
print("running:", ' '.join(cmdargs))
print(" in:", str(py.path.local()))
f1 = codecs.open(str(p1), "w", encoding="utf8")
f2 = codecs.open(str(p2), "w", encoding="utf8")
try:
@@ -918,13 +953,13 @@ class Testdir:
def _dump_lines(self, lines, fp):
try:
for line in lines:
py.builtin.print_(line, file=fp)
print(line, file=fp)
except UnicodeEncodeError:
print("couldn't print to %s because of encoding" % (fp,))
def _getpytestargs(self):
# we cannot use "(sys.executable,script)"
# because on windows the script is e.g. a py.test.exe
# because on windows the script is e.g. a pytest.exe
return (sys.executable, _pytest_fullpath,) # noqa
def runpython(self, script):
@@ -939,7 +974,7 @@ class Testdir:
return self.run(sys.executable, "-c", command)
def runpytest_subprocess(self, *args, **kwargs):
"""Run py.test as a subprocess with given arguments.
"""Run pytest as a subprocess with given arguments.
Any plugins added to the :py:attr:`plugins` list will added
using the ``-p`` command line option. Addtionally
@@ -967,15 +1002,15 @@ class Testdir:
return self.run(*args)
def spawn_pytest(self, string, expect_timeout=10.0):
"""Run py.test using pexpect.
"""Run pytest using pexpect.
This makes sure to use the right py.test and sets up the
This makes sure to use the right pytest and sets up the
temporary directory locations.
The pexpect child is returned.
"""
basetemp = self.tmpdir.mkdir("pexpect")
basetemp = self.tmpdir.mkdir("temp-pexpect")
invoke = " ".join(map(str, self._getpytestargs()))
cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
return self.spawn(cmd, expect_timeout=expect_timeout)
@@ -988,8 +1023,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")
@@ -1035,6 +1068,7 @@ class LineMatcher:
def __init__(self, lines):
self.lines = lines
self._log_output = []
def str(self):
"""Return the entire original text."""
@@ -1058,10 +1092,11 @@ class LineMatcher:
for line in lines2:
for x in self.lines:
if line == x or fnmatch(x, line):
print_("matched: ", repr(line))
self._log("matched: ", repr(line))
break
else:
raise ValueError("line %r not found in output" % line)
self._log("line %r not found in output" % line)
raise ValueError(self._log_text)
def get_lines_after(self, fnline):
"""Return all lines following the given line in the text.
@@ -1073,6 +1108,13 @@ class LineMatcher:
return self.lines[i+1:]
raise ValueError("line %r not found in output" % fnline)
def _log(self, *args):
self._log_output.append(' '.join((str(x) for x in args)))
@property
def _log_text(self):
return '\n'.join(self._log_output)
def fnmatch_lines(self, lines2):
"""Search the text for matching lines.
@@ -1082,8 +1124,6 @@ class LineMatcher:
stdout.
"""
def show(arg1, arg2):
py.builtin.print_(arg1, arg2, file=sys.stderr)
lines2 = self._getlines(lines2)
lines1 = self.lines[:]
nextline = None
@@ -1094,17 +1134,18 @@ class LineMatcher:
while lines1:
nextline = lines1.pop(0)
if line == nextline:
show("exact match:", repr(line))
self._log("exact match:", repr(line))
break
elif fnmatch(nextline, line):
show("fnmatch:", repr(line))
show(" with:", repr(nextline))
self._log("fnmatch:", repr(line))
self._log(" with:", repr(nextline))
break
else:
if not nomatchprinted:
show("nomatch:", repr(line))
self._log("nomatch:", repr(line))
nomatchprinted = True
show(" and:", repr(nextline))
self._log(" and:", repr(nextline))
extralines.append(nextline)
else:
pytest.fail("remains unmatched: %r, see stderr" % (line,))
self._log("remains unmatched: %r" % (line,))
pytest.fail(self._log_text)

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
""" recording warnings during test function execution. """
from __future__ import absolute_import, division, print_function
import inspect
@@ -6,11 +7,11 @@ import _pytest._code
import py
import sys
import warnings
import pytest
from _pytest.fixtures import yield_fixture
@pytest.yield_fixture
def recwarn(request):
@yield_fixture
def recwarn():
"""Return a WarningsRecorder instance that provides these methods:
* ``pop(category=None)``: return last warning matching the category.
@@ -25,39 +26,37 @@ def recwarn(request):
yield wrec
def pytest_namespace():
return {'deprecated_call': deprecated_call,
'warns': warns}
def deprecated_call(func=None, *args, **kwargs):
""" assert that calling ``func(*args, **kwargs)`` triggers a
``DeprecationWarning`` or ``PendingDeprecationWarning``.
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
triggered twice for the same module. See #1190.
"""
if not func:
return WarningsChecker(expected_warning=DeprecationWarning)
return WarningsChecker(expected_warning=(DeprecationWarning, PendingDeprecationWarning))
categories = []
def warn_explicit(message, category, *args, **kwargs):
categories.append(category)
old_warn_explicit(message, category, *args, **kwargs)
def warn(message, category=None, *args, **kwargs):
if isinstance(message, Warning):
categories.append(message.__class__)
else:
categories.append(category)
old_warn(message, category, *args, **kwargs)
old_warn = warnings.warn
old_warn_explicit = warnings.warn_explicit
@@ -110,24 +109,14 @@ def warns(expected_warning, *args, **kwargs):
return func(*args[1:], **kwargs)
class RecordedWarning(object):
def __init__(self, message, category, filename, lineno, file, line):
self.message = message
self.category = category
self.filename = filename
self.lineno = lineno
self.file = file
self.line = line
class WarningsRecorder(object):
class WarningsRecorder(warnings.catch_warnings):
"""A context manager to record raised warnings.
Adapted from `warnings.catch_warnings`.
"""
def __init__(self, module=None):
self._module = sys.modules['warnings'] if module is None else module
def __init__(self):
super(WarningsRecorder, self).__init__(record=True)
self._entered = False
self._list = []
@@ -164,38 +153,20 @@ class WarningsRecorder(object):
if self._entered:
__tracebackhide__ = True
raise RuntimeError("Cannot enter %r twice" % self)
self._entered = True
self._filters = self._module.filters
self._module.filters = self._filters[:]
self._showwarning = self._module.showwarning
def showwarning(message, category, filename, lineno,
file=None, line=None):
self._list.append(RecordedWarning(
message, category, filename, lineno, file, line))
# still perform old showwarning functionality
self._showwarning(
message, category, filename, lineno, file=file, line=line)
self._module.showwarning = showwarning
# allow the same warning to be raised more than once
self._module.simplefilter('always')
self._list = super(WarningsRecorder, self).__enter__()
warnings.simplefilter('always')
return self
def __exit__(self, *exc_info):
if not self._entered:
__tracebackhide__ = True
raise RuntimeError("Cannot exit %r without entering first" % self)
self._module.filters = self._filters
self._module.showwarning = self._showwarning
super(WarningsRecorder, self).__exit__(*exc_info)
class WarningsChecker(WarningsRecorder):
def __init__(self, expected_warning=None, module=None):
super(WarningsChecker, self).__init__(module=module)
def __init__(self, expected_warning=None):
super(WarningsChecker, self).__init__()
msg = ("exceptions must be old-style classes or "
"derived from Warning, not %s")
@@ -216,6 +187,11 @@ class WarningsChecker(WarningsRecorder):
# only check if we're not currently handling an exception
if all(a is None for a in exc_info):
if self.expected_warning is not None:
if not any(r.category in self.expected_warning for r in self):
if not any(issubclass(r.category, self.expected_warning)
for r in self):
__tracebackhide__ = True
pytest.fail("DID NOT WARN")
from _pytest.runner import fail
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

@@ -1,6 +1,7 @@
""" log machine-parseable test session result information in a plain
text file.
"""
from __future__ import absolute_import, division, print_function
import py
import os
@@ -9,7 +10,7 @@ def pytest_addoption(parser):
group = parser.getgroup("terminal reporting", "resultlog plugin options")
group.addoption('--resultlog', '--result-log', action="store",
metavar="path", default=None,
help="path for machine-readable result log.")
help="DEPRECATED path for machine-readable result log.")
def pytest_configure(config):
resultlog = config.option.resultlog
@@ -22,6 +23,9 @@ def pytest_configure(config):
config._resultlog = ResultLog(config, logfile)
config.pluginmanager.register(config._resultlog)
from _pytest.deprecated import RESULT_LOG
config.warn('C1', RESULT_LOG)
def pytest_unconfigure(config):
resultlog = getattr(config, '_resultlog', None)
if resultlog:
@@ -58,9 +62,9 @@ class ResultLog(object):
self.logfile = logfile # preferably line buffered
def write_log_entry(self, testpath, lettercode, longrepr):
py.builtin.print_("%s %s" % (lettercode, testpath), file=self.logfile)
print("%s %s" % (lettercode, testpath), file=self.logfile)
for line in longrepr.splitlines():
py.builtin.print_(" %s" % line, file=self.logfile)
print(" %s" % line, file=self.logfile)
def log_outcome(self, report, lettercode, longrepr):
testpath = getattr(report, 'nodeid', None)

View File

@@ -1,20 +1,14 @@
""" basic collect and runtest protocol implementations """
from __future__ import absolute_import, division, print_function
import bdb
import sys
from time import time
import py
import pytest
from _pytest._code.code import TerminalRepr, ExceptionInfo
def pytest_namespace():
return {
'fail' : fail,
'skip' : skip,
'importorskip' : importorskip,
'exit' : exit,
}
#
# pytest plugin hooks
@@ -73,7 +67,10 @@ def runtestprotocol(item, log=True, nextitem=None):
rep = call_and_report(item, "setup", log)
reports = [rep]
if rep.passed:
reports.append(call_and_report(item, "call", log))
if item.config.option.setupshow:
show_test_item(item)
if not item.config.option.setuponly:
reports.append(call_and_report(item, "call", log))
reports.append(call_and_report(item, "teardown", log,
nextitem=nextitem))
# after all teardown hooks have been called
@@ -83,6 +80,16 @@ def runtestprotocol(item, log=True, nextitem=None):
item.funcargs = None
return reports
def show_test_item(item):
"""Show test function, parameters and the fixtures of the test item."""
tw = item.config.get_terminal_writer()
tw.line()
tw.write(' ' * 8)
tw.write(item._nodeid)
used_fixtures = sorted(item._fixtureinfo.name2fixturedefs.keys())
if used_fixtures:
tw.write(' (fixtures used: {0})'.format(', '.join(used_fixtures)))
def pytest_runtest_setup(item):
item.session._setupstate.prepare(item)
@@ -198,6 +205,36 @@ class BaseReport(object):
if name.startswith(prefix):
yield prefix, content
@property
def longreprtext(self):
"""
Read-only property that returns the full string representation
of ``longrepr``.
.. versionadded:: 3.0
"""
tw = py.io.TerminalWriter(stringio=True)
tw.hasmarkup = False
self.toterminal(tw)
exc = tw.stringio.getvalue()
return exc.strip()
@property
def capstdout(self):
"""Return captured text from stdout, if capturing is enabled
.. versionadded:: 3.0
"""
return ''.join(content for (prefix, content) in self.get_sections('Captured stdout'))
@property
def capstderr(self):
"""Return captured text from stderr, if capturing is enabled
.. versionadded:: 3.0
"""
return ''.join(content for (prefix, content) in self.get_sections('Captured stderr'))
passed = property(lambda x: x.outcome == "passed")
failed = property(lambda x: x.outcome == "failed")
skipped = property(lambda x: x.outcome == "skipped")
@@ -219,7 +256,7 @@ def pytest_runtest_makereport(item, call):
if not isinstance(excinfo, ExceptionInfo):
outcome = "failed"
longrepr = excinfo
elif excinfo.errisinstance(pytest.skip.Exception):
elif excinfo.errisinstance(skip.Exception):
outcome = "skipped"
r = excinfo._getreprcrash()
longrepr = (str(r.path), r.lineno, r.message)
@@ -263,8 +300,10 @@ class TestReport(BaseReport):
#: one of 'setup', 'call', 'teardown' to indicate runtest phase.
self.when = when
#: list of (secname, data) extra information which needs to
#: marshallable
#: list of pairs ``(str, str)`` of extra information which needs to
#: marshallable. Used by pytest to add captured text
#: from ``stdout`` and ``stderr``, but may be used by other plugins
#: to add arbitrary information to reports.
self.sections = list(sections)
#: time it took to run just the test
@@ -285,7 +324,9 @@ class TeardownErrorReport(BaseReport):
self.__dict__.update(extra)
def pytest_make_collect_report(collector):
call = CallInfo(collector._memocollect, "memocollect")
call = CallInfo(
lambda: list(collector.collect()),
'collect')
longrepr = None
if not call.excinfo:
outcome = "passed"
@@ -447,10 +488,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"):
@@ -464,8 +511,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
@@ -474,8 +523,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.
@@ -484,6 +536,8 @@ def fail(msg="", pytrace=True):
"""
__tracebackhide__ = True
raise Failed(msg=msg, pytrace=pytrace)
fail.Exception = Failed
@@ -492,12 +546,23 @@ def importorskip(modname, minversion=None):
__version__ attribute. If no minversion is specified the a skip
is only triggered if the module can not be imported.
"""
import warnings
__tracebackhide__ = True
compile(modname, '', 'eval') # to catch syntaxerrors
try:
__import__(modname)
except ImportError:
skip("could not import %r" %(modname,))
should_skip = False
with warnings.catch_warnings():
# make sure to ignore ImportWarnings that might happen because
# of existing directories with the same name we're trying to
# import but without a __init__.py file
warnings.simplefilter('ignore')
try:
__import__(modname)
except ImportError:
# Do not raise chained exception here(#1485)
should_skip = True
if should_skip:
raise Skipped("could not import %r" %(modname,), allow_module_level=True)
mod = sys.modules[modname]
if minversion is None:
return mod
@@ -506,10 +571,10 @@ 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

74
_pytest/setuponly.py Normal file
View File

@@ -0,0 +1,74 @@
from __future__ import absolute_import, division, print_function
import pytest
import sys
def pytest_addoption(parser):
group = parser.getgroup("debugconfig")
group.addoption('--setuponly', '--setup-only', action="store_true",
help="only setup fixtures, do not execute tests.")
group.addoption('--setupshow', '--setup-show', action="store_true",
help="show setup of fixtures while executing tests.")
@pytest.hookimpl(hookwrapper=True)
def pytest_fixture_setup(fixturedef, request):
yield
config = request.config
if config.option.setupshow:
if hasattr(request, 'param'):
# Save the fixture parameter so ._show_fixture_action() can
# display it now and during the teardown (in .finish()).
if fixturedef.ids:
if callable(fixturedef.ids):
fixturedef.cached_param = fixturedef.ids(request.param)
else:
fixturedef.cached_param = fixturedef.ids[
request.param_index]
else:
fixturedef.cached_param = request.param
_show_fixture_action(fixturedef, 'SETUP')
def pytest_fixture_post_finalizer(fixturedef):
if hasattr(fixturedef, "cached_result"):
config = fixturedef._fixturemanager.config
if config.option.setupshow:
_show_fixture_action(fixturedef, 'TEARDOWN')
if hasattr(fixturedef, "cached_param"):
del fixturedef.cached_param
def _show_fixture_action(fixturedef, msg):
config = fixturedef._fixturemanager.config
capman = config.pluginmanager.getplugin('capturemanager')
if capman:
out, err = capman.suspendcapture()
tw = config.get_terminal_writer()
tw.line()
tw.write(' ' * 2 * fixturedef.scopenum)
tw.write('{step} {scope} {fixture}'.format(
step=msg.ljust(8), # align the output to TEARDOWN
scope=fixturedef.scope[0].upper(),
fixture=fixturedef.argname))
if msg == 'SETUP':
deps = sorted(arg for arg in fixturedef.argnames if arg != 'request')
if deps:
tw.write(' (fixtures used: {0})'.format(', '.join(deps)))
if hasattr(fixturedef, 'cached_param'):
tw.write('[{0}]'.format(fixturedef.cached_param))
if capman:
capman.resumecapture()
sys.stdout.write(out)
sys.stderr.write(err)
@pytest.hookimpl(tryfirst=True)
def pytest_cmdline_main(config):
if config.option.setuponly:
config.option.setupshow = True

25
_pytest/setupplan.py Normal file
View File

@@ -0,0 +1,25 @@
from __future__ import absolute_import, division, print_function
import pytest
def pytest_addoption(parser):
group = parser.getgroup("debugconfig")
group.addoption('--setupplan', '--setup-plan', action="store_true",
help="show what fixtures and tests would be executed but "
"don't execute anything.")
@pytest.hookimpl(tryfirst=True)
def pytest_fixture_setup(fixturedef, request):
# Will return a dummy fixture if the setuponly option is provided.
if request.config.option.setupplan:
fixturedef.cached_result = (None, None, None)
return fixturedef.cached_result
@pytest.hookimpl(tryfirst=True)
def pytest_cmdline_main(config):
if config.option.setupplan:
config.option.setuponly = True
config.option.setupshow = True

View File

@@ -1,12 +1,14 @@
""" support for skip/xfail functions and markers. """
from __future__ import absolute_import, division, print_function
import os
import sys
import traceback
import py
import pytest
from _pytest.config import hookimpl
from _pytest.mark import MarkInfo, MarkDecorator
from _pytest.runner import fail, skip
def pytest_addoption(parser):
group = parser.getgroup("general")
@@ -23,10 +25,14 @@ def pytest_addoption(parser):
def pytest_configure(config):
if config.option.runxfail:
# yay a hack
import pytest
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 +50,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 "
@@ -53,11 +59,7 @@ def pytest_configure(config):
)
def pytest_namespace():
return dict(xfail=xfail)
class XFailed(pytest.fail.Exception):
class XFailed(fail.Exception):
""" raised from an explicit call to pytest.xfail() """
@@ -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
@@ -96,52 +100,47 @@ class MarkEvaluator:
except Exception:
self.exc = sys.exc_info()
if isinstance(self.exc[1], SyntaxError):
msg = [" " * (self.exc[1].offset + 4) + "^",]
msg = [" " * (self.exc[1].offset + 4) + "^", ]
msg.append("SyntaxError: invalid syntax")
else:
msg = traceback.format_exception_only(*self.exc[:2])
pytest.fail("Error evaluating %r expression\n"
" %s\n"
"%s"
%(self.name, self.expr, "\n".join(msg)),
pytrace=False)
fail("Error evaluating %r expression\n"
" %s\n"
"%s"
% (self.name, self.expr, "\n".join(msg)),
pytrace=False)
def _getglobals(self):
d = {'os': os, 'sys': sys, 'config': self.item.config}
func = self.item.obj
try:
d.update(func.__globals__)
except AttributeError:
d.update(func.func_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
# MarkInfo keeps track of all parameters it received in an
# _arglist attribute
if hasattr(self.holder, '_arglist'):
arglist = self.holder._arglist
else:
arglist = [(self.holder.args, self.holder.kwargs)]
for args, kwargs in arglist:
marks = getattr(self.holder, '_marks', None) \
or [self.holder.mark]
for _, args, kwargs in marks:
if 'condition' in kwargs:
args = (kwargs['condition'],)
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:
# XXX better be checked at collection time
msg = "you need to specify reason=STRING " \
"when using booleans as conditions."
pytest.fail(msg)
fail(msg)
result = bool(expr)
if result:
self.result = True
@@ -165,7 +164,7 @@ class MarkEvaluator:
return expl
@pytest.hookimpl(tryfirst=True)
@hookimpl(tryfirst=True)
def pytest_runtest_setup(item):
# Check if skip or skipif are specified as pytest marks
@@ -174,23 +173,23 @@ def pytest_runtest_setup(item):
eval_skipif = MarkEvaluator(item, 'skipif')
if eval_skipif.istrue():
item._evalskip = eval_skipif
pytest.skip(eval_skipif.getexplanation())
skip(eval_skipif.getexplanation())
skip_info = item.keywords.get('skip')
if isinstance(skip_info, (MarkInfo, MarkDecorator)):
item._evalskip = True
if 'reason' in skip_info.kwargs:
pytest.skip(skip_info.kwargs['reason'])
skip(skip_info.kwargs['reason'])
elif skip_info.args:
pytest.skip(skip_info.args[0])
skip(skip_info.args[0])
else:
pytest.skip("unconditional skip")
skip("unconditional skip")
item._evalxfail = MarkEvaluator(item, 'xfail')
check_xfail_no_run(item)
@pytest.mark.hookwrapper
@hookimpl(hookwrapper=True)
def pytest_pyfunc_call(pyfuncitem):
check_xfail_no_run(pyfuncitem)
outcome = yield
@@ -205,7 +204,7 @@ def check_xfail_no_run(item):
evalxfail = item._evalxfail
if evalxfail.istrue():
if not evalxfail.get('run', True):
pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
xfail("[NOTRUN] " + evalxfail.getexplanation())
def check_strict_xfail(pyfuncitem):
@@ -217,10 +216,10 @@ def check_strict_xfail(pyfuncitem):
if is_strict_xfail:
del pyfuncitem._evalxfail
explanation = evalxfail.getexplanation()
pytest.fail('[XPASS(strict)] ' + explanation, pytrace=False)
fail('[XPASS(strict)] ' + explanation, pytrace=False)
@pytest.hookimpl(hookwrapper=True)
@hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
@@ -228,12 +227,19 @@ def pytest_runtest_makereport(item, call):
evalskip = getattr(item, '_evalskip', None)
# unitttest special case, see setting of _unexpectedsuccess
if hasattr(item, '_unexpectedsuccess') and rep.when == "call":
# we need to translate into how pytest encodes xpass
rep.wasxfail = "reason: " + repr(item._unexpectedsuccess)
rep.outcome = "failed"
from _pytest.compat import _is_unittest_unexpected_success_a_failure
if item._unexpectedsuccess:
rep.longrepr = "Unexpected success: {0}".format(item._unexpectedsuccess)
else:
rep.longrepr = "Unexpected success"
if _is_unittest_unexpected_success_a_failure():
rep.outcome = "failed"
else:
rep.outcome = "passed"
rep.wasxfail = rep.longrepr
elif item.config.option.runxfail:
pass # don't interefere
elif call.excinfo and call.excinfo.errisinstance(pytest.xfail.Exception):
elif call.excinfo and call.excinfo.errisinstance(xfail.Exception):
rep.wasxfail = "reason: " + call.excinfo.value.msg
rep.outcome = "skipped"
elif evalxfail and not rep.skipped and evalxfail.wasvalid() and \
@@ -245,8 +251,15 @@ def pytest_runtest_makereport(item, call):
rep.outcome = "skipped"
rep.wasxfail = evalxfail.getexplanation()
elif call.when == "call":
rep.outcome = "failed" # xpass outcome
rep.wasxfail = evalxfail.getexplanation()
strict_default = item.config.getini('xfail_strict')
is_strict_xfail = evalxfail.get('strict', strict_default)
explanation = evalxfail.getexplanation()
if is_strict_xfail:
rep.outcome = "failed"
rep.longrepr = "[XPASS(strict)] {0}".format(explanation)
else:
rep.outcome = "passed"
rep.wasxfail = explanation
elif evalskip is not None and rep.skipped and type(rep.longrepr) is tuple:
# skipped by mark.skipif; change the location of the failure
# to point to the item definition, otherwise it will display
@@ -260,7 +273,7 @@ def pytest_report_teststatus(report):
if hasattr(report, "wasxfail"):
if report.skipped:
return "xfailed", "x", "xfail"
elif report.failed:
elif report.passed:
return "xpassed", "X", ("XPASS", {'yellow': True})
# called by the terminalreporter instance/plugin
@@ -294,12 +307,14 @@ def pytest_terminal_summary(terminalreporter):
for line in lines:
tr._tw.line(line)
def show_simple(terminalreporter, lines, stat, format):
failed = terminalreporter.stats.get(stat)
if failed:
for rep in failed:
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
lines.append(format %(pos,))
lines.append(format % (pos,))
def show_xfailed(terminalreporter, lines):
xfailed = terminalreporter.stats.get("xfailed")
@@ -311,13 +326,15 @@ def show_xfailed(terminalreporter, lines):
if reason:
lines.append(" " + str(reason))
def show_xpassed(terminalreporter, lines):
xpassed = terminalreporter.stats.get("xpassed")
if xpassed:
for rep in xpassed:
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
reason = rep.wasxfail
lines.append("XPASS %s %s" %(pos, reason))
lines.append("XPASS %s %s" % (pos, reason))
def cached_eval(config, expr, d):
if not hasattr(config, '_evalcache'):
@@ -342,6 +359,7 @@ def folded_skips(skipped):
l.append((len(events),) + key)
return l
def show_skipped(terminalreporter, lines):
tr = terminalreporter
skipped = tr.stats.get('skipped', [])
@@ -357,5 +375,6 @@ def show_skipped(terminalreporter, lines):
for num, fspath, lineno, reason in fskips:
if reason.startswith("Skipped: "):
reason = reason[9:]
lines.append("SKIP [%d] %s:%d: %s" %
lines.append(
"SKIP [%d] %s:%d: %s" %
(num, fspath, lineno, reason))

View File

@@ -1,89 +0,0 @@
#! /usr/bin/env python
# Hi There!
# You may be wondering what this giant blob of binary data here is, you might
# even be worried that we're up to something nefarious (good for you for being
# paranoid!). This is a base64 encoding of a zip file, this zip file contains
# a fully functional basic pytest script.
#
# Pytest is a thing that tests packages, pytest itself is a package that some-
# one might want to install, especially if they're looking to run tests inside
# some package they want to install. Pytest has a lot of code to collect and
# execute tests, and other such sort of "tribal knowledge" that has been en-
# coded in its code base. Because of this we basically include a basic copy
# of pytest inside this blob. We do this because it let's you as a maintainer
# or application developer who wants people who don't deal with python much to
# easily run tests without installing the complete pytest package.
#
# If you're wondering how this is created: you can create it yourself if you
# have a complete pytest installation by using this command on the command-
# line: ``py.test --genscript=runtests.py``.
sources = """
@SOURCES@"""
import sys
import base64
import zlib
class DictImporter(object):
def __init__(self, sources):
self.sources = sources
def find_module(self, fullname, path=None):
if fullname == "argparse" and sys.version_info >= (2,7):
# we were generated with <python2.7 (which pulls in argparse)
# but we are running now on a stdlib which has it, so use that.
return None
if fullname in self.sources:
return self
if fullname + '.__init__' in self.sources:
return self
return None
def load_module(self, fullname):
# print "load_module:", fullname
from types import ModuleType
try:
s = self.sources[fullname]
is_pkg = False
except KeyError:
s = self.sources[fullname + '.__init__']
is_pkg = True
co = compile(s, fullname, 'exec')
module = sys.modules.setdefault(fullname, ModuleType(fullname))
module.__file__ = "%s/%s" % (__file__, fullname)
module.__loader__ = self
if is_pkg:
module.__path__ = [fullname]
do_exec(co, module.__dict__) # noqa
return sys.modules[fullname]
def get_source(self, name):
res = self.sources.get(name)
if res is None:
res = self.sources.get(name + '.__init__')
return res
if __name__ == "__main__":
try:
import pkg_resources # noqa
except ImportError:
sys.stderr.write("ERROR: setuptools not installed\n")
sys.exit(2)
if sys.version_info >= (3, 0):
exec("def do_exec(co, loc): exec(co, loc)\n")
import pickle
sources = sources.encode("ascii") # ensure bytes
sources = pickle.loads(zlib.decompress(base64.decodebytes(sources)))
else:
import cPickle as pickle
exec("def do_exec(co, loc): exec co in loc\n")
sources = pickle.loads(zlib.decompress(base64.decodestring(sources)))
importer = DictImporter(sources)
sys.meta_path.insert(0, importer)
entry = "@ENTRY@"
do_exec(entry, locals()) # noqa

View File

@@ -2,6 +2,9 @@
This is a good source for looking at the various reporting hooks.
"""
from __future__ import absolute_import, division, print_function
import itertools
from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \
EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED
import pytest
@@ -20,16 +23,18 @@ def pytest_addoption(parser):
group._addoption('-q', '--quiet', action="count",
dest="quiet", default=0, help="decrease verbosity."),
group._addoption('-r',
action="store", dest="reportchars", default=None, metavar="chars",
action="store", dest="reportchars", default='', metavar="chars",
help="show extra test summary info as specified by chars (f)ailed, "
"(E)error, (s)skipped, (x)failed, (X)passed (w)pytest-warnings "
"(p)passed, (P)passed with output, (a)all except pP.")
"(E)error, (s)skipped, (x)failed, (X)passed, "
"(p)passed, (P)passed with output, (a)all except pP. "
"Warnings are displayed at all times except when "
"--disable-warnings is set")
group._addoption('--disable-warnings', '--disable-pytest-warnings', default=False,
dest='disable_warnings', action='store_true',
help='disable warnings summary')
group._addoption('-l', '--showlocals',
action="store_true", dest="showlocals", default=False,
help="show locals in tracebacks (disabled by default).")
group._addoption('--report',
action="store", dest="report", default=None, metavar="opts",
help="(deprecated, use -r)")
group._addoption('--tb', metavar="style",
action="store", dest="tbstyle", default='auto',
choices=['auto', 'long', 'short', 'no', 'line', 'native'],
@@ -54,18 +59,11 @@ def pytest_configure(config):
def getreportopt(config):
reportopts = ""
optvalue = config.option.report
if optvalue:
py.builtin.print_("DEPRECATED: use -r instead of --report option.",
file=sys.stderr)
if optvalue:
for setting in optvalue.split(","):
setting = setting.strip()
if setting == "skipped":
reportopts += "s"
elif setting == "xfailed":
reportopts += "x"
reportchars = config.option.reportchars
if not config.option.disable_warnings and 'w' not in reportchars:
reportchars += 'w'
elif config.option.disable_warnings and 'w' in reportchars:
reportchars = reportchars.replace('w', '')
if reportchars:
for char in reportchars:
if char not in reportopts and char != 'a':
@@ -85,13 +83,40 @@ def pytest_report_teststatus(report):
letter = "f"
return report.outcome, letter, report.outcome.upper()
class WarningReport:
"""
Simple structure to hold warnings information captured by ``pytest_logwarning``.
"""
def __init__(self, code, message, nodeid=None, fslocation=None):
"""
:param code: unused
:param str message: user friendly message about the warning
:param str|None nodeid: node id that generated the warning (see ``get_location``).
:param tuple|py.path.local fslocation:
file system location of the source of the warning (see ``get_location``).
"""
self.code = code
self.message = message
self.nodeid = nodeid
self.fslocation = fslocation
def get_location(self, config):
"""
Returns the more user-friendly information about the location
of a warning, or None.
"""
if self.nodeid:
return self.nodeid
if self.fslocation:
if isinstance(self.fslocation, tuple) and len(self.fslocation) >= 2:
filename, linenum = self.fslocation[:2]
relpath = py.path.local(filename).relto(config.invocation_dir)
return '%s:%s' % (relpath, linenum)
else:
return str(self.fslocation)
return None
class TerminalReporter:
def __init__(self, config, file=None):
@@ -171,8 +196,6 @@ class TerminalReporter:
def pytest_logwarning(self, code, fslocation, message, nodeid):
warnings = self.stats.setdefault("warnings", [])
if isinstance(fslocation, tuple):
fslocation = "%s:%d" % fslocation
warning = WarningReport(code=code, fslocation=fslocation,
message=message, nodeid=nodeid)
warnings.append(warning)
@@ -300,8 +323,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:
@@ -366,7 +389,8 @@ class TerminalReporter:
EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, EXIT_USAGEERROR,
EXIT_NOTESTSCOLLECTED)
if exitstatus in summary_exit_codes:
self.config.hook.pytest_terminal_summary(terminalreporter=self)
self.config.hook.pytest_terminal_summary(terminalreporter=self,
exitstatus=exitstatus)
self.summary_errors()
self.summary_failures()
self.summary_warnings()
@@ -442,13 +466,21 @@ class TerminalReporter:
def summary_warnings(self):
if self.hasopt("w"):
warnings = self.stats.get("warnings")
if not warnings:
all_warnings = self.stats.get("warnings")
if not all_warnings:
return
self.write_sep("=", "pytest-warning summary")
for w in warnings:
self._tw.line("W%s %s %s" % (w.code,
w.fslocation, w.message))
grouped = itertools.groupby(all_warnings, key=lambda wr: wr.get_location(self.config))
self.write_sep("=", "warnings summary", yellow=True, bold=False)
for location, warnings in grouped:
self._tw.line(str(location) or '<undetermined location>')
for w in warnings:
lines = w.message.splitlines()
indented = '\n'.join(' ' + x for x in lines)
self._tw.line(indented)
self._tw.line()
self._tw.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html')
def summary_passes(self):
if self.config.option.tbstyle != "no":
@@ -462,6 +494,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')
@@ -477,6 +518,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":
@@ -517,16 +561,8 @@ class TerminalReporter:
def summary_deselected(self):
if 'deselected' in self.stats:
l = []
k = self.config.option.keyword
if k:
l.append("-k%s" % k)
m = self.config.option.markexpr
if m:
l.append("-m %r" % m)
if l:
self.write_sep("=", "%d tests deselected by %r" % (
len(self.stats['deselected']), " ".join(l)), bold=True)
self.write_sep("=", "%d tests deselected" % (
len(self.stats['deselected'])), bold=True)
def repr_pythonversion(v=None):
if v is None:
@@ -546,8 +582,7 @@ def flatten(l):
def build_summary_stats_line(stats):
keys = ("failed passed skipped deselected "
"xfailed xpassed warnings error").split()
key_translation = {'warnings': 'pytest-warnings'}
"xfailed xpassed warnings error").split()
unknown_key_seen = False
for key in stats.keys():
if key not in keys:
@@ -558,8 +593,7 @@ def build_summary_stats_line(stats):
for key in keys:
val = stats.get(key, None)
if val:
key_name = key_translation.get(key, key)
parts.append("%d %s" % (len(val), key_name))
parts.append("%d %s" % (len(val), key))
if parts:
line = ", ".join(parts)

View File

@@ -1,9 +1,11 @@
""" support for providing temporary directories to test functions. """
from __future__ import absolute_import, division, print_function
import re
import pytest
import py
from _pytest.monkeypatch import monkeypatch
from _pytest.monkeypatch import MonkeyPatch
class TempdirFactory:
@@ -81,6 +83,7 @@ def get_user():
except (ImportError, KeyError):
return None
# backward compatibility
TempdirHandler = TempdirFactory
@@ -92,7 +95,7 @@ def pytest_configure(config):
available at pytest_configure time, but ideally should be moved entirely
to the tmpdir_factory session fixture.
"""
mp = monkeypatch()
mp = MonkeyPatch()
t = TempdirFactory(config)
config._cleanup.extend([mp.undo, t.finish])
mp.setattr(config, '_tmpdirhandler', t, raising=False)
@@ -108,14 +111,14 @@ def tmpdir_factory(request):
@pytest.fixture
def tmpdir(request, tmpdir_factory):
"""return a temporary directory path object
"""Return a temporary directory path object
which is unique to each test function invocation,
created as a sub directory of the base temporary
directory. The returned object is a `py.path.local`_
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

@@ -1,14 +1,15 @@
""" discovery and running of std-library "unittest" style tests. """
from __future__ import absolute_import
from __future__ import absolute_import, division, print_function
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
from _pytest.config import hookimpl
from _pytest.runner import fail, skip
from _pytest.python import transfer_markers, Class, Module, Function
from _pytest.skipping import MarkEvaluator, xfail
def pytest_pycollect_makeitem(collector, name, obj):
@@ -22,11 +23,11 @@ def pytest_pycollect_makeitem(collector, name, obj):
return UnitTestCase(name, parent=collector)
class UnitTestCase(pytest.Class):
class UnitTestCase(Class):
# marker for fixturemanger.getfixtureinfo()
# to declare that our children do not support funcargs
nofuncargs = True
def setup(self):
cls = self.obj
if getattr(cls, '__unittest_skip__', False):
@@ -46,10 +47,12 @@ class UnitTestCase(pytest.Class):
return
self.session._fixturemanager.parsefactories(self, unittest=True)
loader = TestLoader()
module = self.getparent(pytest.Module).obj
module = self.getparent(Module).obj
foundsomething = False
for name in loader.getTestCaseNames(self.obj):
x = getattr(self.obj, name)
if not getattr(x, '__test__', True):
continue
funcobj = getattr(x, 'im_func', x)
transfer_markers(funcobj, cls, module)
yield TestCaseFunction(name, parent=self)
@@ -63,8 +66,7 @@ class UnitTestCase(pytest.Class):
yield TestCaseFunction('runTest', parent=self)
class TestCaseFunction(pytest.Function):
class TestCaseFunction(Function):
_excinfo = None
def setup(self):
@@ -92,6 +94,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
@@ -106,36 +111,37 @@ class TestCaseFunction(pytest.Function):
try:
l = traceback.format_exception(*rawexcinfo)
l.insert(0, "NOTE: Incompatible Exception Representation, "
"displaying natively:\n\n")
pytest.fail("".join(l), pytrace=False)
except (pytest.fail.Exception, KeyboardInterrupt):
"displaying natively:\n\n")
fail("".join(l), pytrace=False)
except (fail.Exception, KeyboardInterrupt):
raise
except:
pytest.fail("ERROR: Unknown Incompatible Exception "
"representation:\n%r" %(rawexcinfo,), pytrace=False)
fail("ERROR: Unknown Incompatible Exception "
"representation:\n%r" % (rawexcinfo,), pytrace=False)
except KeyboardInterrupt:
raise
except pytest.fail.Exception:
except fail.Exception:
excinfo = _pytest._code.ExceptionInfo()
self.__dict__.setdefault('_excinfo', []).append(excinfo)
def addError(self, testcase, rawexcinfo):
self._addexcinfo(rawexcinfo)
def addFailure(self, testcase, rawexcinfo):
self._addexcinfo(rawexcinfo)
def addSkip(self, testcase, reason):
try:
pytest.skip(reason)
except pytest.skip.Exception:
skip(reason)
except skip.Exception:
self._evalskip = MarkEvaluator(self, 'SkipTest')
self._evalskip.result = True
self._addexcinfo(sys.exc_info())
def addExpectedFailure(self, testcase, rawexcinfo, reason=""):
try:
pytest.xfail(str(reason))
except pytest.xfail.Exception:
xfail(str(reason))
except xfail.Exception:
self._addexcinfo(sys.exc_info())
def addUnexpectedSuccess(self, testcase, reason=""):
@@ -147,17 +153,42 @@ 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)
Function._prunetraceback(self, excinfo)
traceback = excinfo.traceback.filter(
lambda x:not x.frame.f_globals.get('__unittest'))
lambda x: not x.frame.f_globals.get('__unittest'))
if traceback:
excinfo.traceback = traceback
@pytest.hookimpl(tryfirst=True)
@hookimpl(tryfirst=True)
def pytest_runtest_makereport(item, call):
if isinstance(item, TestCaseFunction):
if item._excinfo:
@@ -169,13 +200,15 @@ def pytest_runtest_makereport(item, call):
# twisted trial support
@pytest.hookimpl(hookwrapper=True)
@hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item):
if isinstance(item, TestCaseFunction) and \
'twisted.trial.unittest' in sys.modules:
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:
@@ -189,6 +222,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)
@@ -528,7 +540,7 @@ class PluginManager(object):
of HookImpl instances and the keyword arguments for the hook call.
``after(outcome, hook_name, hook_impls, kwargs)`` receives the
same arguments as ``before`` but also a :py:class:`_CallOutcome`` object
same arguments as ``before`` but also a :py:class:`_CallOutcome <_pytest.vendored_packages.pluggy._CallOutcome>` object
which represents the result of the overall hook call.
"""
return _TracedHookExecution(self, before, after).undo
@@ -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" % (

88
_pytest/warnings.py Normal file
View File

@@ -0,0 +1,88 @@
from __future__ import absolute_import, division, print_function
import warnings
from contextlib import contextmanager
import pytest
from _pytest import compat
def _setoption(wmod, arg):
"""
Copy of the warning._setoption function but does not escape arguments.
"""
parts = arg.split(':')
if len(parts) > 5:
raise wmod._OptionError("too many fields (max 5): %r" % (arg,))
while len(parts) < 5:
parts.append('')
action, message, category, module, lineno = [s.strip()
for s in parts]
action = wmod._getaction(action)
category = wmod._getcategory(category)
if lineno:
try:
lineno = int(lineno)
if lineno < 0:
raise ValueError
except (ValueError, OverflowError):
raise wmod._OptionError("invalid lineno %r" % (lineno,))
else:
lineno = 0
wmod.filterwarnings(action, message, category, module, lineno)
def pytest_addoption(parser):
group = parser.getgroup("pytest-warnings")
group.addoption(
'-W', '--pythonwarnings', action='append',
help="set which warnings to report, see -W option of python itself.")
parser.addini("filterwarnings", type="linelist",
help="Each line specifies warning filter pattern which would be passed"
"to warnings.filterwarnings. Process after -W and --pythonwarnings.")
@contextmanager
def catch_warnings_for_item(item):
"""
catches the warnings generated during setup/call/teardown execution
of the given item and after it is done posts them as warnings to this
item.
"""
args = item.config.getoption('pythonwarnings') or []
inifilters = item.config.getini("filterwarnings")
with warnings.catch_warnings(record=True) as log:
for arg in args:
warnings._setoption(arg)
for arg in inifilters:
_setoption(warnings, arg)
yield
for warning in log:
warn_msg = warning.message
unicode_warning = False
if compat._PY2 and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args):
new_args = [compat.safe_str(m) for m in warn_msg.args]
unicode_warning = warn_msg.args != new_args
warn_msg.args = new_args
msg = warnings.formatwarning(
warn_msg, warning.category,
warning.filename, warning.lineno, warning.line)
item.warn("unused", msg)
if unicode_warning:
warnings.warn(
"Warning is using unicode non convertible to ascii, "
"converting to a safe representation:\n %s" % msg,
UnicodeWarning)
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item):
with catch_warnings_for_item(item):
yield

View File

@@ -5,24 +5,38 @@ environment:
# using pytestbot account as detailed here:
# https://www.appveyor.com/docs/build-configuration#secure-variables
matrix:
# 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

39
changelog/_template.rst Normal file
View File

@@ -0,0 +1,39 @@
{% for section in sections %}
{% set underline = "-" %}
{% if section %}
{{section}}
{{ underline * section|length }}{% set underline = "~" %}
{% endif %}
{% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section] and category != 'trivial' %}
{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}
{% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category]|dictsort(by='value') %}
- {{ text }}{% if category != 'vendor' %} ({{ values|sort|join(', ') }}){% endif %}
{% endfor %}
{% else %}
- {{ sections[section][category]['']|sort|join(', ') }}
{% endif %}
{% if sections[section][category]|length == 0 %}
No significant changes.
{% else %}
{% endif %}
{% endfor %}
{% else %}
No significant changes.
{% endif %}
{% endfor %}

View File

@@ -17,12 +17,16 @@ REGENDOC_ARGS := \
--normalize "/_{8,} (.*) _{8,}/_______ \1 ________/" \
--normalize "/in \d+.\d+ seconds/in 0.12 seconds/" \
--normalize "@/tmp/pytest-of-.*/pytest-\d+@PYTEST_TMPDIR@" \
--normalize "@pytest-(\d+)\\.[^ ,]+@pytest-\1.x.y@" \
--normalize "@(This is pytest version )(\d+)\\.[^ ,]+@\1\2.x.y@" \
--normalize "@py-(\d+)\\.[^ ,]+@py-\1.x.y@" \
--normalize "@pluggy-(\d+)\\.[.\d,]+@pluggy-\1.x.y@" \
--normalize "@hypothesis-(\d+)\\.[.\d,]+@hypothesis-\1.x.y@" \
--normalize "@Python (\d+)\\.[^ ,]+@Python \1.x.y@"
.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,24 +40,8 @@ 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}
PYTHONDONTWRITEBYTECODE=1 PYTEST_ADDOPT=-pno:hypothesis COLUMNS=76 regendoc --update *.rst */*.rst ${REGENDOC_ARGS}
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html

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

@@ -1,19 +1,5 @@
{% extends "!layout.html" %}
{% block header %}
<div align="center" xmlns="http://www.w3.org/1999/html" style="background-color: lightgreen; padding: .5em">
<h4>
Want to help improve pytest? Please
<a href="https://www.indiegogo.com/projects/python-testing-sprint-mid-2016#/">
contribute to
</a>
or
<a href="announce/sprint2016.html">
join
</a>
our upcoming sprint in June 2016!
</h4>
</div>
{{super()}}
{% endblock %}
{% block footer %}

View File

@@ -1,16 +1,11 @@
<h3>Useful Links</h3>
<ul>
<li>
<a href="https://www.indiegogo.com/projects/python-testing-sprint-mid-2016#/">
<b>Sprint funding campaign</b>
</a>
</li>
<li><a href="{{ pathto('index') }}">The pytest Website</a></li>
<li><a href="{{ pathto('contributing') }}">Contribution Guide</a></li>
<li><a href="https://pypi.python.org/pypi/pytest">pytest @ PyPI</a></li>
<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,9 +5,20 @@ Release announcements
.. toctree::
:maxdepth: 2
release-3.1.2
release-3.1.1
release-3.1.0
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.1
release-2.9.2
release-2.9.1
release-2.9.0
release-2.8.7

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

@@ -1,4 +1,4 @@
pytest-2.9.1
pytest-2.9.2
============
pytest is a mature Python testing tool with more than a 1100 tests
@@ -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

@@ -0,0 +1,82 @@
pytest-3.0.0
============
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 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.
There's a "What's new in pytest 3.0" [2] blog post highlighting the
major features in this release.
To see the complete changelog and documentation, please visit:
http://docs.pytest.org
As usual, you can upgrade from pypi via:
pip install -U pytest
Thanks to all who contributed to this release, among them:
AbdealiJK
Ana Ribeiro
Antony Lee
Brandon W Maister
Brianna Laugher
Bruno Oliveira
Ceridwen
Christian Boelsen
Daniel Hahler
Danielle Jenkins
Dave Hunt
Diego Russo
Dmitry Dygalo
Edoardo Batini
Eli Boyarski
Florian Bruhin
Floris Bruynooghe
Greg Price
Guyzmo
HEAD KANGAROO
JJ
Javi Romero
Javier Domingo Cansino
Kale Kundert
Kalle Bronsen
Marius Gedminas
Matt Williams
Mike Lundy
Oliver Bestwalter
Omar Kohl
Raphael Pierzina
RedBeardCode
Roberto Polli
Romain Dorgueil
Roman Bolshakov
Ronny Pfannschmidt
Stefan Zimmermann
Steffen Allner
Tareq Alayan
Ted Xiao
Thomas Grainger
Tom Viner
TomV
Vasily Kuznetsov
aostr
marscher
palaviv
satoru
taschini
Happy testing,
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

@@ -0,0 +1,61 @@
pytest-3.1.0
=======================================
The pytest team is proud to announce the 3.1.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 bugs fixes and improvements, so users are encouraged
to take a look at the CHANGELOG:
http://doc.pytest.org/en/latest/changelog.html
For complete documentation, please visit:
http://docs.pytest.org
As usual, you can upgrade from pypi via:
pip install -U pytest
Thanks to all who contributed to this release, among them:
* Anthony Sottile
* Ben Lloyd
* Bruno Oliveira
* David Giese
* David Szotten
* Dmitri Pribysh
* Florian Bruhin
* Florian Schulze
* Floris Bruynooghe
* John Towler
* Jonas Obrist
* Katerina Koukiou
* Kodi Arfer
* Krzysztof Szularz
* Lev Maximov
* Loïc Estève
* Luke Murphy
* Manuel Krebber
* Matthew Duck
* Matthias Bussonnier
* Michael Howitz
* Michal Wajszczuk
* Paweł Adamczak
* Rafael Bertoldi
* Ravi Chandra
* Ronny Pfannschmidt
* Skylar Downes
* Thomas Kriechbaumer
* Vitaly Lashmanov
* Vlad Dragos
* Wheerd
* Xander Johnson
* mandeep
* reut
Happy testing,
The Pytest Development Team

View File

@@ -0,0 +1,23 @@
pytest-3.1.1
=======================================
pytest 3.1.1 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:
* Bruno Oliveira
* Florian Bruhin
* Floris Bruynooghe
* Jason R. Coombs
* Ronny Pfannschmidt
* wanghui
Happy testing,
The pytest Development Team

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