`tox -vv` is too verbose, and was only used as a hack to get the output
of durations.
As for information in logs `-v` could be used maybe still, but I've
decided to revert it for now.
This reverts commit 56cec5fa79.
Source was previously iterable because it implements `__getitem__()`,
which is apparently a thing from before `__iter__()` was introduced.
To reduce mypy's and my own confusion, implement `__iter__()` directly.
The previous test was better in that it used fakes to test all of the
real code paths. The problem with that is that it makes it impossible to
simplify the code with `isinstance` checks. So let's just simulate the
issue directly with a monkeypatch.
Add some Python 3.8 type: ignores; all are already fixed in the next
mypy release, so can be removed once we upgrade.
Also move some flake8 ignores which seem to have changed places.
Instead of giving an example of using sys and then, at the end,
advising not to use sys, just give a correct example. This is
especially helpful since mypy 0.740 has started (correctly) complaining
about sys._called_from_pytest not being present.
It currently fails with a TypeError, and was not updated since 2013 -
therefore it can be assumed that it is not important to support it.
```
____________________ ERROR collecting test_nested_marks.py _____________________
…/Vcs/pluggy/src/pluggy/hooks.py:286: in __call__
return self._hookexec(self, self.get_hookimpls(), kwargs)
…/Vcs/pluggy/src/pluggy/manager.py:93: in _hookexec
return self._inner_hookexec(hook, methods, kwargs)
…/Vcs/pluggy/src/pluggy/manager.py:337: in traced_hookexec
return outcome.get_result()
…/Vcs/pluggy/src/pluggy/manager.py:335: in <lambda>
outcome = _Result.from_call(lambda: oldcall(hook, hook_impls, kwargs))
…/Vcs/pluggy/src/pluggy/manager.py:87: in <lambda>
firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
…/Vcs/pytest/src/_pytest/python.py:235: in pytest_pycollect_makeitem
res = list(collector._genfunctions(name, obj))
…/Vcs/pytest/src/_pytest/python.py:404: in _genfunctions
self.ihook.pytest_generate_tests.call_extra(methods, dict(metafunc=metafunc))
…/Vcs/pluggy/src/pluggy/hooks.py:324: in call_extra
return self(**kwargs)
…/Vcs/pluggy/src/pluggy/hooks.py:286: in __call__
return self._hookexec(self, self.get_hookimpls(), kwargs)
…/Vcs/pluggy/src/pluggy/manager.py:93: in _hookexec
return self._inner_hookexec(hook, methods, kwargs)
…/Vcs/pluggy/src/pluggy/manager.py:337: in traced_hookexec
return outcome.get_result()
…/Vcs/pluggy/src/pluggy/manager.py:335: in <lambda>
outcome = _Result.from_call(lambda: oldcall(hook, hook_impls, kwargs))
…/Vcs/pluggy/src/pluggy/manager.py:87: in <lambda>
firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
…/Vcs/pytest/src/_pytest/python.py:130: in pytest_generate_tests
metafunc.parametrize(*marker.args, **marker.kwargs)
…/Vcs/pytest/src/_pytest/python.py:965: in parametrize
function_definition=self.definition,
…/Vcs/pytest/src/_pytest/mark/structures.py:111: in _for_parametrize
if len(param.values) != len(argnames):
E TypeError: object of type 'MarkDecorator' has no len()
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
```
This comes via hypothesis:
```
% COLUMNS=80 p testing/python/metafunc.py::TestMetafunc::test_idval_hypothesis -vv --tb=short
============================= test session starts ==============================
platform linux -- Python 3.7.4, pytest-3.1.4.dev721+g3367bf03b.d20191112, py-1.8.1.dev11+g34f716fe, pluggy-0.13.1.dev8+ga5130ac.d20191103 -- …/Vcs/pytest/.venv/bin/python
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('…/Vcs/pytest/.hypothesis/examples')
rootdir: …/Vcs/pytest, inifile: tox.ini
plugins: forked-1.1.3, hypothesis-4.44.1, cov-2.8.1, coverage-pytest-plugin-0.1, enhancements-0.0.5.dev1-gf361636-dirty, xdist-1.30.0
collected 1 item
testing/python/metafunc.py::TestMetafunc::test_idval_hypothesis FAILED [100%]
=================================== FAILURES ===================================
______________________ TestMetafunc.test_idval_hypothesis ______________________
.venv/lib/python3.7/site-packages/hypothesis/core.py:588: in evaluate_test_data
result = self.execute(data)
.venv/lib/python3.7/site-packages/hypothesis/core.py:553: in execute
result = self.test_runner(data, run)
.venv/lib/python3.7/site-packages/hypothesis/executors.py:56: in default_new_style_executor
return function(data)
.venv/lib/python3.7/site-packages/hypothesis/core.py:536: in run
args, kwargs = data.draw(self.search_strategy)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:857: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/core.py:223: in do_draw
return self.mapped_strategy.do_draw(data)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: in do_draw
return tuple(data.draw(e) for e in self.element_strategies)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: in <genexpr>
return tuple(data.draw(e) for e in self.element_strategies)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:570: in do_draw
result = self.pack(data.draw(self.mapped_strategy))
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: in do_draw
return data.draw(self.wrapped_strategy)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:570: in do_draw
result = self.pack(data.draw(self.mapped_strategy))
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: in do_draw
return tuple(data.draw(e) for e in self.element_strategies)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:60: in <genexpr>
return tuple(data.draw(e) for e in self.element_strategies)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:508: in do_draw
return data.draw(self.element_strategies[i], label=self.branch_labels[i])
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: in do_draw
return data.draw(self.wrapped_strategy)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/strategies.py:570: in do_draw
result = self.pack(data.draw(self.mapped_strategy))
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/lazy.py:156: in do_draw
return data.draw(self.wrapped_strategy)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/collections.py:120: in do_draw
result.append(data.draw(self.element_strategy))
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:852: in draw
return strategy.do_draw(self)
.venv/lib/python3.7/site-packages/hypothesis/searchstrategy/numbers.py:62: in do_draw
return d.integer_range(data, self.start, self.end)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/utils.py:105: in integer_range
probe = data.draw_bits(bits)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:974: in draw_bits
self.__check_capacity(n_bytes)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:1019: in __check_capacity
self.mark_overrun()
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:1036: in mark_overrun
self.conclude_test(Status.OVERRUN)
.venv/lib/python3.7/site-packages/hypothesis/internal/conjecture/data.py:1027: in conclude_test
raise StopTest(self.testcounter)
E hypothesis.errors.StopTest: 0
During handling of the above exception, another exception occurred:
testing/python/metafunc.py:195: in test_idval_hypothesis
@hypothesis.settings(
.venv/lib/python3.7/site-packages/nose/__init__.py:1: in <module>
from nose.core import collector, main, run, run_exit, runmodule
.venv/lib/python3.7/site-packages/nose/core.py:12: in <module>
from nose.loader import defaultTestLoader
.venv/lib/python3.7/site-packages/nose/loader.py:21: in <module>
from nose.importer import Importer, add_path, remove_path
.venv/lib/python3.7/site-packages/nose/importer.py:12: in <module>
from imp import find_module, load_module, acquire_model1, release_model1
/usr/lib/python3.7/imp.py:33: in <module>
DeprecationWarning, stacklevel=2)
E DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
---------------------------------- Hypothesis ----------------------------------
You can add @seed(198901559535749756451579900660745168041) to this test or run pytest with --hypothesis-seed=198901559535749756451579900660745168041 to reproduce this failure.
=============================== warnings summary ===============================
testing/python/metafunc.py::TestMetafunc::test_idval_hypothesis
…/Vcs/pytest/.venv/lib/python3.7/site-packages/unittest2/compatibility.py:143: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
class ChainMap(collections.MutableMapping):
-- Docs: https://docs.pytest.org/en/latest/warnings.html
=========================== short test summary info ============================
FAILED testing/python/metafunc.py::TestMetafunc::test_idval_hypothesis - Depr...
```
This is a useful utility to abstract the caching property idiom.
It is in compat.py since eventually it will be replaced by
functools.cached_property.
Fixes#6131.
It is a little too obscure IMO, but the reason I want to drop it is that
type checking has no hope of understanding such dynamic constructs.
The warning argument wasn't used.
This is already covered by attrs.
Also, the custom implementation returns False when the types don't
match, but it's better to return `NotImplemented`. attrs does this.
This fixes/removes the previous hack of re-trying with minimum width,
which fails short when it splits strings.
This inherits from `pprint.PrettyPrinter` to override `_format` in a
minimal way to always dispatch, regardless of the given width.
Code ref: 5c0c325453/Lib/pprint.py (L170-L178)
Harden one test where it is tested.
All tests testing this:
testing/acceptance_test.py:184(TestGeneralUsage::test_not_collectable_arguments)
testing/acceptance_test.py:373(TestGeneralUsage::test_direct_addressing_notfound)
testing/acceptance_test.py:403(TestGeneralUsage::test_issue134_report_error_when_collecting_member[test_fun.py::test_a])
testing/acceptance_test.py:420(TestGeneralUsage::test_report_all_failed_collections_initargs)
testing/test_config.py:1309(test_config_blocked_default_plugins[python])
(via https://github.com/blueyed/pytest/pull/88)
Works around:
_____ ERROR collecting testing/io/test_saferepr.py _____
src/_pytest/python.py:502: in _importtestmodule
mod = self.fspath.pyimport(ensuresyspath=importmode)
.venv38/lib/python3.8/site-packages/py/_path/local.py:701: in pyimport
__import__(modname)
<frozen importlib._bootstrap>:991: in _find_and_load
???
<frozen importlib._bootstrap>:975: in _find_and_load_unlocked
???
<frozen importlib._bootstrap>:671: in _load_unlocked
???
src/_pytest/assertion/rewrite.py:136: in exec_module
source_stat, co = _rewrite_test(fn, self.config)
src/_pytest/assertion/rewrite.py:288: in _rewrite_test
co = compile(tree, fn, "exec", dont_inherit=True)
E File "…/Vcs/pytest/testing/io/test_saferepr.py", line 45
E None()
E ^
E SyntaxError: 'NoneType' object is not callable; perhaps you missed a comma?
This causes INTERNALERRORs with pytest-django, which uses
`pytest.fail` (derived from `BaseException`) to prevent DB access, when
pytest then tries to e.g. display the `repr()` for a Django `QuerySet`
etc.
Ref: https://github.com/pytest-dev/pytest-django/pull/776
Follow-up to 946434c61 (#5924).
Before this patch the test would look like this:
{'env': {'sub...s wrapped'}}}} == {'env': {'sub...}}}, 'new': 1}
Omitting 1 identical items, use -vv to show
Right contains 1 more item:
{'new': 1}
Full diff:
{
'env': {'sub': {'long_a': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
- 'sub1': {'long_a': 'substring '
+ 'sub1': {'long_a': 'substring that gets wrapped'}}},
? +++++++++++++++++ ++++
+ 'new': 1,
- 'that '
- 'gets '
- 'wrapped'}}},
}
indicate current outcome/status with color of percentage indicator
Fix type annotation, refactor _write_progress_information_filling_space
Keep code in _get_main_color as similar as possible to how it was before
Write test
Make black-compliant
Fix error in newly introduced test_collecterror
Make tests more readable by using constants and f-strings
Remove accidentally added monkeypatch
Make Python 3.5-compatible, add changelog entry
Add newline at the end of changelog file
Remove the `--fulltrace` arg from the `Option` fixture used in several
tests, but not checked for. Only use it with `test_keyboard_interrupt`.
(removes 8 tests, coverage not affected)
The function handles bytes input, however that is never used.
The function has two callers:
1)
```
if istext(left) and istext(right):
explanation = _diff_text(left, right, verbose
```
`istext` checks `isinstance(str)`.
2)
```
def _notin_text(term: str, text: str, verbose: int = 0) -> List[str]:
...
diff = _diff_text(correct_text, text, verbose
```
and `_notin_text` is called once:
```
if istext(left) and istext(right):
explanation = _notin_text(left, right, verbose
```
Without this, the second time it tries to stop in a parametrized
function it raises instead:
`ValueError: --trace can't be used with a fixture named func!`
Implementation idea, test (and changelog tweaks) thanks to blueyed
Co-Authored-By: Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
Co-Authored-By: Daniel Hahler <git@thequod.de>
Failed for me due to different indent (?) - not reproducible:
> ???
E Failed: nomatch: 'E TypeError: write() argument must be str, not bytes'
…
E and: '> def mode(self):'
E and: 'E TypeError: write() argument must be str, not bytes'
…
E remains unmatched: 'E TypeError: write() argument must be str, not bytes'
This would prevent TOXENV=py37-pexpect-… from running on e.g. FreeBSD.
And even on Windows it is pytest's job of skipping the tests then. This
was probably still from when the pexpect env was only running
pexpect-based tests.
Tidelift has launched a new marketing campaign as outlined here:
* https://forum.tidelift.com/t/task-enhancement-marketing-the-tidelift-subscription-to-your-users/321
This PR splits the previous "sponsor" information into two, Open Collective
and Tidelift (as they have very different target audiences).
Also took the opportunity to reorder some items at the end of
the contents page in a manner that I believe make more sense.
In order to make the LiteralOutputChecker lazy initialization more
amenable to type checking, I changed it to match the scheme already used
in this file to lazy-initialize PytestDoctestRunner.
Changelogs:
http://mypy-lang.blogspot.com/2019/09/mypy-730-released.htmlhttp://mypy-lang.blogspot.com/2019/10/mypy-0740-released.html
New errors:
src/_pytest/recwarn.py:77: error: Missing return statement
src/_pytest/recwarn.py:185: error: "bool" is invalid as return type for "__exit__" that always returns False
src/_pytest/recwarn.py:185: note: Use "typing_extensions.Literal[False]" as the return type or change it to "None"
src/_pytest/recwarn.py:185: note: If return type of "__exit__" implies that it may return True, the context manager may swallow exceptions
src/_pytest/recwarn.py:185: error: Return type "bool" of "__exit__" incompatible with return type "None" in supertype "catch_warnings"
src/_pytest/recwarn.py:230: error: "bool" is invalid as return type for "__exit__" that always returns False
src/_pytest/recwarn.py:230: note: Use "typing_extensions.Literal[False]" as the return type or change it to "None"
src/_pytest/recwarn.py:230: note: If return type of "__exit__" implies that it may return True, the context manager may swallow exceptions
src/_pytest/recwarn.py:230: error: Return type "bool" of "__exit__" incompatible with return type "None" in supertype "catch_warnings"
The errors are due to this new error:
https://mypy.readthedocs.io/en/latest/error_code_list.html#check-the-return-type-of-exit-exit-return
This is important when used with ``pytester``'s ``runpytest_inprocess``.
Since 07f20ccab `pytest testing/acceptance_test.py -k test_doctest_id`
would fail, since the second run would not consider the exception to be
an instance of `doctest.DocTestFailure` anymore, since the module was
re-imported, and use another failure message then in the short test
summary info (and in the report itself):
> FAILED test_doctest_id.txt::test_doctest_id.txt - doctest.DocTestFailure: <Do...
while it should be:
> FAILED test_doctest_id.txt::test_doctest_id.txt
This avoids mutating the original list to reflect on InvocationParams,
which is supposed to be an immutable snapshot of the state of pytest.main()
at the moment of invocation (see pytest-dev/pytest-xdist#478).
Massage text input for difflib when comparing pformat output of
different line lengths.
Also do not strip ndiff output on the left, which currently already
removes indenting for lines with no differences.
Before:
E AssertionError: assert ['version', '...version_info'] == ['version', '...version', ...]
E Right contains 3 more items, first extra item: ' '
E Full diff:
E - ['version', 'version_info', 'sys.version', 'sys.version_info']
E + ['version',
E + 'version_info',
E + 'sys.version',
E + 'sys.version_info',
E + ' ',
E + 'sys.version',
E + 'sys.version_info']
After:
E AssertionError: assert ['version', '...version_info'] == ['version', '...version', ...]
E Right contains 3 more items, first extra item: ' '
E Full diff:
E [
E 'version',
E 'version_info',
E 'sys.version',
E 'sys.version_info',
E + ' ',
E + 'sys.version',
E + 'sys.version_info',
E ]
The current idiom is to use:
assert re.match(pat, result.stdout.str())
Or
assert line in result.stdout.str()
But this does not really give good results when it fails.
Those new functions produce similar output to ther other match lines functions.
attrs 19.2 deprecated cmp in favor of the dataclass-ish eq/order duo.
This causes deprecation warnings that in turn break some of the cool new deep
object comparisons. Since we at attrs expected this to be a problem, it shipped
with helpers to write backward and forward compatible code.
This PR uses that and avoids changed to minimal versions.
Recently sometimes Azure has failed with:
++ curl -s https://codecov.io/bash
bash: /dev/fd/63: No such file or directory
This attempts to fix this by modifying report-coverage.sh slightly.
As discussed in the mailing list, pytest will join the
digital strike for the climate on Sep 20th. This will show
a closable banner on the docs until the date, and when the date
comes the banner will become a (closable) full page.
I will also pin an issue saying that the developers won't be
available on Sep 20th.
Using Path().resolve() is better than py.path.realpath because
it resolves to the correct path/drive in case-insensitive file systems (#5792):
>>> from py.path import local
>>> from pathlib import Path
>>>
>>> local('d:\\projects').realpath()
local('d:\\projects')
>>> Path('d:\\projects').resolve()
WindowsPath('D:/projects')
Fix#5819
We find that the --pastebin option to pytest sometimes fails with "HTTP
Error 400: Bad Request". We're still investigating the exact cause of
these errors, but in the meantime, a failure to upload to the pastebin
service should probably not crash pytest and cause a test failure in the
continuous-integration.
This patch catches exceptions like HTTPError that may be thrown while
trying to communicate with the pastebin service, and reports them as a
"bad response", without crashing with a backtrace or failing the entire
test suite.
`argparse.HelpFormatter` looks at `$COLUMNS` only, falling back to a
default of 80.
`py.io.get_terminal_width()` is smarter there, and could even work
better with https://github.com/pytest-dev/py/pull/219.
This ensures to use a consistent value for formatting the ini values etc.
The typing module on these versions have these issues:
- `typing.Pattern` cannot appear in a Union since it is not considered a
class.
- `@overload` is not supported in runtime. (On the other hand, mypy
doesn't support putting it under `if False`, so we need some runtime
hack).
Refs #5751.
The only benefit for me is to get notified about finished builds, but
that might happen to early anyway. Apart from that they are rather big
and distract from actual comments.
I was doing final tests on the script today, and forgot to change
the hardecoded "pytest-dev/pytest", which ended up publishing a
`4.99.10` release to the main repository by mistake, as my token
has access to both my fork and main repository.
I deleted the tag immeditely just a few seconds later, so hopefully
this won't cause major problems.
This change makes it safer to test this in the future, never publishing
to the main repository by mistake (as long as the tags are pushed to the
right repositories of course).
Previously it would say:
> assert '123456789012...901234567890A' == '1234567890123...901234567890B'"
This makes it look like the "3" might be different already.
This is clearer, and it is OK to have potentially one less char in the
right one:
> assert '123456789012...901234567890A' == '123456789012...901234567890B'"
This creates a separate section from 'features' for small changes which
don't usually require user intervention, such as:
* Human readable session duration
* New junitxml fields
* Improved colors in terminal
* etc.
The idea is to better match user expectations about new actual
features in the "Features" section of the changelog.
Previously, the test failed when the directory was not present,
which could have been caused for example by invoking the tests
with PYTHONDONTWRITEBYTECODE=1.
Fixes https://github.com/pytest-dev/pytest/issues/5664
Map `BdbQuit` exception to `outcomes.Exit`.
This is necessary since we are not wrapping `pdb.set_trace` there, and
therefore our `do_quit` is not called.
It seems to have been added in #1439 to fix#1178.
This was only relevant for Python 2 where it was tempting to use str (==
bytes) literals instead of unicode literals. In Python 3, it is unlikely
that anyone passes bytes to these functions.
This makes testing/ actually pick up the pytest imports -- otherwise
they are opaque and we don't actually test the types.
A single run is also a bit faster and simpler. The original reason why
we split it is no longer relevant (we fixed the problems).
This function is not called anywhere directly, and cannot be called by
the dynamic `repr_<type>()` dispatch mechanism because unicode is no
longer a type in Python 3.
This reverts commit dfe54cd82f.
The idea in the commit was to simplify the code by removing the check
and instead letting it TypeError which has the same effect.
However this type error is caught by mypy, and rather than ignoring the
error we think it's better and clearer to go back to the previous
explicit check.
A case with a fixture use both as an autouse and explititly
was raised. This case sounds too narrow to add to documentation
(and could be misleading for people learning pytest with explicitely
using an autouse fixture). At the same time there was no documentation
on the autouse vs regular fixture order, therefore this commit adds
such an information. Code sample grew and it was extracted to the file.
These doctests were expected to fail, but they were failing because of a
silly bug (I forgot to replace "{expression}" with the actual expression
to be tested), not because of the thing they were meant to be testing.
Then I had to fix one of the testcases because it was actually matching:
>>> 3.0 #doctest: +NUMBER
2.99
The doctest is saying that the actual output should match to 2 decimal
places, i.e. within 0.01 -- which it is, so it passes. I changed the
expected output to 2.98 and now it doesn't match (as we expect).
Add a very lax mypy configuration, add it to tox -e linting, and
fix/ignore the few errors that come up. The idea is to get it running
before diving in too much.
This enables:
- Progressively adding type annotations and enabling more strict
options, which will improve the codebase (IMO).
- Annotating the public API in-line, and eventually exposing it to
library users who use type checkers (with a py.typed file).
Though, none of this is done yet.
Refs https://github.com/pytest-dev/pytest/issues/3342.
Add a very lax mypy configuration, add it to tox -e linting, and
fix/ignore the few errors that come up. The idea is to get it running
before diving in too much.
This enables:
- Progressively adding type annotations and enabling more strict
options, which will improve the codebase (IMO).
- Annotating the public API in-line, and eventually exposing it to
library users who use type checkers (with a py.typed file).
Though, none of this is done yet.
Refs https://github.com/pytest-dev/pytest/issues/3342.
This is being raised by `unittest2.compatibility`:
DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
* Move the parts about "how to configure it" (pytest.ini vs. inline
comment) together.
* Move `--doctest-continue-on-failure` into its own sub-heading, as it
isn't related to the doctest optionflags.
When enabled, floating-point numbers only need to match as far as the
precision you have written in the expected doctest output. This avoids
false positives caused by limited floating-point precision, like this:
Expected:
0.233
Got:
0.23300000000000001
This is inspired by Sébastien Boisgérault's [numtest] but the
implementation is a bit different:
* This implementation edits the literals that are in the "got"
string (the actual output from the expression being tested), and then
proceeds to compare the strings literally. This is similar to pytest's
existing ALLOW_UNICODE and ALLOW_BYTES implementation.
* This implementation only compares floats against floats, not ints
against floats. That is, the following doctest will fail with pytest
whereas it would pass with numtest:
>>> math.py # doctest: +NUMBER
3
This behaviour should be less surprising (less false negatives) when
you enable NUMBER globally in pytest.ini.
Advantages of this implementation compared to numtest:
* Doesn't require `import numtest` at the top level of the file.
* Works with pytest (if you try to use pytest & numtest together, pytest
raises "TypeError: unbound method check_output() must be called with
NumTestOutputChecker instance as first argument (got
LiteralsOutputChecker instance instead)").
* Works with Python 3.
[numtest]: https://github.com/boisgera/numtest
These attributes can be used to access the unchanged arguments passed
to pytest.main().
The intention is to use these attributes to initialize workers in
the same manner as the master node is initialized in pytest-xdist.
The following edits are for the "Preparing pull requests" section only.
1. remove Python2-related commands.
2. clarifying some details for beginners. Such as that pre-commit must to be installed as admin to function properly.
3. Added "You may not create a changelog entry if the change doesn't affect the documented behaviour of Pytest." on line 270.
`-ra` / `-rA` will include "w" also. This does not explicitly mention
it (allowing for change the behavior), but makes it a) clearer that "w"
is a recognized reportchar, and b) less confusing that `-ra
--disable-warnings` still displays them.
* Add pytest-faulthandler files unchanged
* Adapt imports and tests
* Add code to skip registration of the external `pytest_faulthandler`
to avoid conflicts
Fix#5440
When we configure warnings as errors, users see error messages like this:
def test():
> warnings.warn(pytest.PytestWarning("some warning"))
E _pytest.warning_types.PytestWarning: some warning
This is a problem because suggests the user should use `_pytest.warning_types.PytestWarning` to configure
their warning filters, which is not nice.
This commit changes the message to:
def test():
> warnings.warn(pytest.PytestWarning("some warning"))
E pytest.PytestWarning: some warning
The function has been deprecated for ages and
the PLUGIN_MANAGER_ADDHOOKS constant doesn't even exist since 3.0.
Because the function is clearly broken, this change doesn't even
require a CHANGELOG.
Since then pytest itself adopted the behavior of interrupting
the test session on collection errors, so --sw no longer needs
to handle this.
The --sw behavior seems have been implemented when pytest
would continue execution even if there were collection errors.
As we did not provide an alternative yet, it is better to postpone
the actual removal until we have provided a suitable and stable
alternative.
Related to #4488
The example implementation of a `--runslow` option results in
a `PytestUnknownMarkWarning`. Include registering the custom
mark in the example, based on the documentation in markers.rst.
* Update setup.py requires and classifiers
* Drop Python 2.7 and 3.4 from CI
* Update docs dropping 2.7 and 3.4 support
* Fix mock imports and remove tests related to pypi's mock module
* Add py27 and 34 support docs to the sidebar
* Remove usage of six from tmpdir
* Remove six.PY* code blocks
* Remove sys.version_info related code
* Cleanup compat
* Remove obsolete safe_str
* Remove obsolete __unicode__ methods
* Remove compat.PY35 and compat.PY36: not really needed anymore
* Remove unused UNICODE_TYPES
* Remove Jython specific code
* Remove some Python 2 references from docs
Related to #5275
A method _create_formatter was introduced that is used for both the
log_cli_formatter and the log_formatter.
Consequences of this commit are:
* Captured logs that are output for each failing test are formatted
using the ColoredLevelFromatter.
* The formatter used for writing to a file still uses the non-colored
logging.Formatter class.
This exposes the functionality introduced in fa6acdc as a session-scoped fixture.
Plugins that want to remain compatible with the `xunit2`
standard should use this fixture instead of `record_property`.
Fix#5202
It doesn't seem to add much value (why would one execute tests
based on that marker?), plus using the docstring for that
encourages one to write a more descriptive message about the test
We improve the following things in the logging format:
* Show module name instead of just the filename
* show level of logging as the first thing
* show lineno attached to module:file details
Thanks to @blueyed who suggested this on the github issue.
It's my first contribution and I have added myself to AUTHORS.
I also added to a changelog file.
This reverts commit e88aa957ae, reversing
changes made to 1410d3dc9a.
I do not think it warrants an option anymore, and there is a way to
achieve this via `--pdbcls` if needed.
`Session.startdir` and `TerminalReporter.startdir` appear to be
redundant given `Config.invocation_dir`.
Keep them for backward compatibility reasons, but use
`config.invocation_dir` for them.
Thanks for submitting a PR, your contribution is really appreciated!
Here's a quick checklist that should be present in PRs.
(please delete this text from the final description, this is just a guideline)
-->
Here is a quick checklist that should be present in PRs.
- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details.
- [ ] Target the `master` branch for bug fixes, documentation updates and trivial changes.
- [ ] Target the `features` branch for new features and removals/deprecations.
- [ ] Target the `features` branch for new features, improvements, and removals/deprecations.
- [ ] Include documentation when adding new features.
- [ ] Include new tests or update existing tests when applicable.
Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:
Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:
- [ ]Add yourself to `AUTHORS` in alphabetical order;
- [ ]Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) fordetails.
- [ ] Add yourself to `AUTHORS` in alphabetical order.
@@ -12,6 +12,7 @@ Each file should be named like ``<ISSUE>.<TYPE>.rst``, where
``<ISSUE>`` is an issue number, and ``<TYPE>`` is one of:
*``feature``: new user facing features, like new command-line options and new behavior.
*``improvement``: improvement of existing functionality, usually without requiring user intervention (for example, new fields being written in ``--junitxml``, improved colors in terminal, etc).
*``bugfix``: fixes a reported bug.
*``doc``: documentation improvement, like rewording an entire session or adding missing docs.
It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies.
.._`nose and unittest`: faq.html#how-does-pytest-relate-to-nose-and-unittest
@@ -19,12 +19,83 @@ Below is a complete list of all pytest features which are considered deprecated.
:class:`_pytest.warning_types.PytestWarning` or subclasses, which can be filtered using
:ref:`standard warning filters <warnings>`.
``junit_family`` default value change to "xunit2"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..deprecated:: 5.2
The default value of ``junit_family`` option will change to ``xunit2`` in pytest 6.0, given
that this is the version supported by default in modern tools that manipulate this type of file.
In order to smooth the transition, pytest will issue a warning in case the ``--junitxml`` option
is given in the command line but ``junit_family`` is not explicitly configured in ``pytest.ini``::
PytestDeprecationWarning: The 'junit_family' default value will change to 'xunit2' in pytest 6.0.
Add 'junit_family=legacy' to your pytest.ini file to silence this warning and make your suite compatible.
In order to silence this warning, users just need to configure the ``junit_family`` option explicitly:
..code-block::ini
[pytest]
junit_family=legacy
``funcargnames`` alias for ``fixturenames``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..deprecated:: 5.0
The ``FixtureRequest``, ``Metafunc``, and ``Function`` classes track the names of
their associated fixtures, with the aptly-named ``fixturenames`` attribute.
Prior to pytest 2.3, this attribute was named ``funcargnames``, and we have kept
that as an alias since. It is finally due for removal, as it is often confusing
in places where we or plugin authors must distinguish between fixture names and
names supplied by non-fixture things such as ``pytest.mark.parametrize``.
Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..deprecated:: 4.0
The ``--result-log`` option produces a stream of test reports which can be
analysed at runtime, but it uses a custom format which requires users to implement their own
parser.
The `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin provides a ``--report-log`` option, a more standard and extensible alternative, producing
one JSON object per-line, and should cover the same use cases. Please try it out and provide feedback.
The plan is remove the ``--result-log`` option in pytest 6.0 if ``pytest-reportlog`` proves satisfactory
to all users and is deemed stable. The ``pytest-reportlog`` plugin might even be merged into the core
at some point, depending on the plans for the plugins and number of users using it.
Removed Features
----------------
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed.
``pytest.config`` global
~~~~~~~~~~~~~~~~~~~~~~~~
..versionremoved:: 5.0
The ``pytest.config`` global object is deprecated. Instead use
``request.config`` (via the ``request`` fixture) or if you are a plugin author
use the ``pytest_configure(config)`` hook. Note that many hooks can also access
the ``config`` object indirectly, through ``session.config`` or ``item.config`` for example.
.._`raises message deprecated`:
``"message"`` parameter of ``pytest.raises``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..deprecated::4.1
..versionremoved::5.0
It is a common mistake to think this parameter will match the exception message, while in fact
it only serves to provide a custom message in case the ``pytest.raises`` check fails. To prevent
@@ -55,22 +126,12 @@ If you still have concerns about this deprecation and future removal, please com
pytest.skip("test requires env in {!r}".format(envnames))
A test file using this local plugin:
@@ -405,14 +406,14 @@ the test needs:
$ pytest -E stage2
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 1 item
test_someenv.py s [100%]
======================== 1 skipped in 0.12 seconds =========================
============================ 1 skipped in 0.12s ============================
and here is one that specifies exactly the environment needed:
@@ -420,14 +421,14 @@ and here is one that specifies exactly the environment needed:
$ pytest -E stage1
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 1 item
test_someenv.py . [100%]
========================= 1 passed in 0.12 seconds =========================
============================ 1 passed in 0.12s =============================
The ``--markers`` option always gives you a list of available markers:
@@ -498,7 +499,7 @@ The output is as follows:
$ pytest -q -s
Mark(name='my_marker', args=(<function hello_world at 0xdeadbeef>,), kwargs={})
.
1 passed in 0.12 seconds
1 passed in 0.12s
We can see that the custom marker has its argument set extended with the function ``hello_world``. This is the key difference between creating a custom marker as a callable, which invokes ``__call__`` behind the scenes, and using ``with_args``.
@@ -522,7 +523,7 @@ code you can read over all such settings. Example:
@pytest.mark.glob("class",x=2)
classTestClass(object):
classTestClass:
@pytest.mark.glob("function",x=3)
deftest_something(self):
pass
@@ -538,7 +539,7 @@ test function. From a conftest file we can read it like this:
Here is an example ``conftest.py`` (extracted from Ali Afshnars special purpose `pytest-yamlwsgi`_ plugin). This ``conftest.py`` will collect ``test*.yml`` files and will execute the yaml-formatted content as custom tests:
Here is an example ``conftest.py`` (extracted from Ali Afshnars special purpose `pytest-yamlwsgi`_ plugin). This ``conftest.py`` will collect ``test*.yaml`` files and will execute the yaml-formatted content as custom tests:
..include:: nonpython/conftest.py
:literal:
You can create a simple example file:
..include:: nonpython/test_simple.yml
..include:: nonpython/test_simple.yaml
:literal:
and if you installed `PyYAML`_ or a compatible YAML-parser you can
@@ -27,21 +27,21 @@ now execute the test specification:
..code-block::pytest
nonpython $ pytest test_simple.yml
nonpython $ pytest test_simple.yaml
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y
@@ -285,7 +315,7 @@ Let's first see how it looks like at collection time:
$ pytest test_backends.py --collect-only
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 2 items
@@ -293,7 +323,7 @@ Let's first see how it looks like at collection time:
<Function test_db_initialized[d1]>
<Function test_db_initialized[d2]>
======================= no tests ran in 0.12 seconds =======================
========================== no tests ran in 0.12s ===========================
And then when we run the test:
@@ -312,8 +342,8 @@ And then when we run the test:
> pytest.fail("deliberately failing for demo purposes")
E Failed: deliberately failing for demo purposes
test_backends.py:6: Failed
1 failed, 1 passed in 0.12 seconds
test_backends.py:8: Failed
1 failed, 1 passed in 0.12s
The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``db`` fixture function has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase.
@@ -327,23 +357,29 @@ parameter on particular arguments. It can be done by passing list or tuple of
arguments' names to ``indirect``. In the example below there is a function ``test_indirect`` which uses
two fixtures: ``x`` and ``y``. Here we give to indirect the list, which contains the name of the
fixture ``x``. The indirect parameter will be applied to this argument only, and the value ``a``
@@ -429,15 +470,16 @@ is to be run with different sets of arguments for its three arguments:
..literalinclude:: multipython.py
Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize):
Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (3 interpreters times 3 interpreters times 3 objects to serialize/deserialize):
..code-block::pytest
. $ pytest -rs -q multipython.py
...sss...sssssssss...sss... [100%]
ssssssssssss...ssssssssssss [100%]
========================= short test summary info ==========================
SKIPPED [15] $REGENDOC_TMPDIR/CWD/multipython.py:30: 'python3.4' not found
12 passed, 15 skipped in 0.12 seconds
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.5' not found
SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:29: 'python3.7' not found
3 passed, 24 skipped in 0.12s
Indirect parametrization of optional implementations/imports
smtp_connection = <smtplib.SMTP object at 0xdeadbeef>
@@ -638,7 +706,7 @@ So let's just do another run:
> assert b"smtp.gmail.com" in msg
E AssertionError: assert b'smtp.gmail.com' in b'mail.python.org\nPIPELINING\nSIZE 51200000\nETRN\nSTARTTLS\nAUTH DIGEST-MD5 NTLM CRAM-MD5\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8\nCHUNKING'
* `Flaky Tests at Google and How We Mitigate Them <https://testing.googleblog.com/2016/05/flaky-tests-at-google-and-how-we.html>`_ by John Micco, 2016
*`Where do Google's flaky tests come from? <https://docs.google.com/document/d/1mZ0-Kc97DI_F3tf_GBW_NB_aqka-P1jVOsFfufxqUUM/edit#heading=h.ec0r4fypsleh>`_ by Jeff Listfield, 2017
*`Where do Google's flaky tests come from? <https://testing.googleblog.com/2017/04/where-do-our-flaky-tests-come-from.html>`_ by Jeff Listfield, 2017
Once you develop multiple tests, you may want to group them into a class. pytest makes it easy to create a class containing more than one test::
Once you develop multiple tests, you may want to group them into a class. pytest makes it easy to create a class containing more than one test:
..code-block::python
# content of test_class.py
classTestClass(object):
class TestClass:
deftest_one(self):
x="this"
assert 'h' in x
assert "h"inx
deftest_two(self):
x="hello"
asserthasattr(x, 'check')
assert hasattr(x,"check")
``pytest`` discovers all tests following its :ref:`Conventions for Python test discovery <test discovery>`, so it finds both ``test_`` prefixed functions. There is no need to subclass anything. We can simply run the module by passing its filename:
@@ -130,19 +140,21 @@ Once you develop multiple tests, you may want to group them into a class. pytest
def test_two(self):
x = "hello"
> assert hasattr(x, 'check')
> assert hasattr(x, "check")
E AssertionError: assert False
E + where False = hasattr('hello', 'check')
test_class.py:8: AssertionError
1 failed, 1 passed in 0.12 seconds
1 failed, 1 passed in 0.12s
The first test passed and the second failed. You can easily see the intermediate values in the assertion to help you understand the reason for the failure.
Request a unique temporary directory for functional tests
``pytest`` provides `Builtin fixtures/function arguments <https://docs.pytest.org/en/latest/builtin.html#builtinfixtures>`_ to request arbitrary resources, like a unique temporary directory::
``pytest`` provides `Builtin fixtures/function arguments <https://docs.pytest.org/en/latest/builtin.html>`_ to request arbitrary resources, like a unique temporary directory:
..code-block::python
# content of test_tmpdir.py
deftest_needsfiles(tmpdir):
@@ -168,7 +180,7 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look
This page lists features or behavior from previous versions of pytest which have changed over the years. They are
kept here as a historical note so users looking at old code can find documentation related to them.
.._marker-revamp:
Marker revamp and iteration
---------------------------
..versionchanged:: 3.6
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to cumulatively add markers. As a result, markers would unintentionally be passed along class hierarchies in surprising ways. Further, the API for retrieving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
On top of that markers were not accessible in the same way for modules, classes, and functions/methods.
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with
the initial design, providing the :func:`_pytest.nodes.Node.iter_markers` method to iterate over
markers in a consistent manner and reworking the internals, which solved a great deal of problems
with the initial design.
.._update marker code:
Updating code
~~~~~~~~~~~~~
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
In general there are two scenarios on how markers should be handled:
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
In this case, use ``Node.get_closest_marker(name)``:
..code-block::python
# replace this:
marker=item.get_marker("log_level")
ifmarker:
level=marker.args[0]
# by this:
marker=item.get_closest_marker("log_level")
ifmarker:
level=marker.args[0]
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
order doesn't even matter. You probably want to think of your marks as a set here.
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
..code-block::python
# replace this
skipif=item.get_marker("skipif")
ifskipif:
forconditioninskipif.args:
# eval condition
...
# by this:
forskipifinitem.iter_markers("skipif"):
condition=skipif.args[0]
# eval condition
If you are unsure or have any questions, please consider opening
"markers","env(name): mark test to run only on named environment"
)
Registered marks appear in pytest's help text and do not emit warnings (see the next section). It
is recommended that third-party plugins always :ref:`register their markers <registering-markers>`.
.._unknown-marks:
Raising errors on unknown marks
-------------------------------
Unregistered marks applied with the ``@pytest.mark.name_of_the_mark`` decorator
will always emit a warning in order to avoid silently doing something
surprising due to mis-typed names. As described in the previous section, you can disable
the warning for custom marks by registering them in your ``pytest.ini`` file or
using a custom ``pytest_configure`` hook.
When the ``--strict-markers`` command-line flag is passed, any unknown marks applied
with the ``@pytest.mark.name_of_the_mark`` decorator will trigger an error. You can
enforce this validation in your project by adding ``--strict-markers`` to ``addopts``:
..code-block::ini
[pytest]
addopts=--strict
addopts=--strict-markers
markers =
slow
slow: marks tests as slow (deselect with '-m "not slow"')
serial
.._marker-revamp:
Marker revamp and iteration
---------------------------
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to cumulatively add markers. As a result, markers would unintentionally be passed along class hierarchies in surprising ways. Further, the API for retrieving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
On top of that markers were not accessible the same way for modules, classes, and functions/methods.
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with the initial design, providing :func:`_pytest.nodes.Node.iter_markers` method to iterate over markers in a consistent manner and reworking the internals, which solved great deal of problems with the initial design.
.._update marker code:
Updating code
~~~~~~~~~~~~~
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
In general there are two scenarios on how markers should be handled:
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
In this case, use ``Node.get_closest_marker(name)``:
..code-block::python
# replace this:
marker=item.get_marker("log_level")
ifmarker:
level=marker.args[0]
# by this:
marker=item.get_closest_marker("log_level")
ifmarker:
level=marker.args[0]
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
order doesn't even matter. You probably want to think of your marks as a set here.
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
..code-block::python
# replace this
skipif=item.get_marker("skipif")
ifskipif:
forconditioninskipif.args:
# eval condition
...
# by this:
forskipifinitem.iter_markers("skipif"):
condition=skipif.args[0]
# eval condition
If you are unsure or have any questions, please consider opening
@@ -7,16 +7,25 @@ Python 3.4's last release is scheduled for
`March 2019 <https://www.python.org/dev/peps/pep-0429/#release-schedule>`__. pytest is one of
the participating projects of the https://python3statement.org.
We plan to drop support for Python 2.7 and 3.4 at the same time with the release of **pytest 5.0**,
scheduled to be released by **mid-2019**. Thanks to the `python_requires <https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires>`__``setuptools`` option,
The **pytest 4.6** series is the last to support Python 2.7 and 3.4, and was released in
**June 2019**. **pytest 5.0** and onwards will support only Python 3.5+.
Thanks to the `python_requires`_``setuptools`` option,
Python 2.7 and Python 3.4 users using a modern ``pip`` version
will install the last compatible pytest ``4.X`` version automatically even if ``5.0`` or later
will install the last pytest ``4.6`` version automatically even if ``5.0`` or later
are available on PyPI.
During the period **from mid-2019 and 2020**, the pytest core team plans to make
bug-fix releases of the pytest ``4.X`` series by back-porting patches to the ``4.x-maintenance``
branch.
While pytest ``5.0`` will be the new mainstream and development version, until **January 2020**
the pytest core team plans to make bug-fix releases of the pytest ``4.6`` series by
back-porting patches to the ``4.6-maintenance`` branch that affect Python 2 users.
**After 2020**, the core team will no longer actively backport-patches, but the ``4.x-maintenance``
branch will continue to exist so the community itself can contribute patches. The
core team will be happy to accept those patches and make new ``4.X`` releases **until mid-2020**.
**After 2020**, the core team will no longer actively backportpatches, but the ``4.6-maintenance``
branch will continue to exist so the community itself can contribute patches. The core team will
be happy to accept those patches and make new ``4.6`` releases **until mid-2020**.
The technical aspects of the Python 2.7 and 3.4 support plan (such as when releases will occurr, how to backport fixes, etc) is described in issue `#5275 <https://github.com/pytest-dev/pytest/issues/5275>`__.
-`pytest: recommendations, basic packages for testing in Python and Django, Andreu Vallbona, PyBCN June 2019 <https://www.slideshare.net/AndreuVallbonaPlazas/pybcn-pytest-recomendaciones-paquetes-bsicos-para-testing-en-python-y-django>`_.
- pytest: recommendations, basic packages for testing in Python and Django, Andreu Vallbona, PyconES 2017 (`slides in english <http://talks.apsl.io/testing-pycones-2017/>`_, `video in spanish <https://www.youtube.com/watch?v=K20GeR-lXDk>`_)
- `pytest advanced, Andrew Svetlov (Russian, PyCon Russia, 2016)
`Tidelift`_ is working with the maintainers of pytest and thousands of other
open source projects to deliver commercial support and maintenance for the open source dependencies you use
to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the
exact dependencies you use.
`Get more details <https://tidelift.com/subscription/pkg/pypi-pytest?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=enterprise>`_
The Tidelift Subscription is a managed open source subscription for application dependencies covering millions of open source projects across JavaScript, Python, Java, PHP, Ruby, .NET, and more.
Your subscription includes:
***Security updates**
- Tidelift's security response team coordinates patches for new breaking security vulnerabilities and alerts immediately through a private channel, so your software supply chain is always secure.
***Licensing verification and indemnification**
- Tidelift verifies license information to enable easy policy enforcement and adds intellectual property indemnification to cover creators and users in case something goes wrong. You always have a 100% up-to-date bill of materials for your dependencies to share with your legal team, customers, or partners.
***Maintenance and code improvement**
- Tidelift ensures the software you rely on keeps working as long as you need it to work. Your managed dependencies are actively maintained and we recruit additional maintainers where required.
***Package selection and version guidance**
- Tidelift helps you choose the best open source packages from the start—and then guide you through updates to stay on the best releases as new issues arise.
***Roadmap input**
- Take a seat at the table with the creators behind the software you use. Tidelift's participating maintainers earn more income as their software is used by more subscribers, so they're interested in knowing what you need.
***Tooling and cloud integration**
- Tidelift works with GitHub, GitLab, BitBucket, and every cloud platform (and other deployment targets, too).
The end result? All of the capabilities you expect from commercial-grade software, for the full breadth of open
source you use. That means less time grappling with esoteric open source trivia, and more time building your own
applications—and your business.
`Request a demo <https://tidelift.com/subscription/request-a-demo?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=enterprise>`_
.._Tidelift: https://tidelift.com
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.