Skip to content

Commit

Permalink
Merge pull request #4158 from nicoddemus/merge-master-into-features
Browse files Browse the repository at this point in the history
Merge master into features (prepare for 3.9, pt2)
  • Loading branch information
nicoddemus committed Oct 15, 2018
2 parents 58b6e86 + 9646a1c commit e4e4fd1
Show file tree
Hide file tree
Showing 21 changed files with 177 additions and 103 deletions.
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Expand Up @@ -3,7 +3,7 @@ Thanks for submitting a PR, your contribution is really appreciated!
Here's a quick checklist that should be present in PRs (you can delete this text from the final description, this is
just a guideline):

- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](/changelog/README.rst) for details.
- [ ] 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.
- [ ] Include documentation when adding new features.
Expand Down
14 changes: 5 additions & 9 deletions .travis.yml
Expand Up @@ -12,19 +12,15 @@ install:
- pip install --upgrade --pre tox
env:
matrix:
# note: please use "tox --listenvs" to populate the build matrix below
# please remove the linting env in all cases
- TOXENV=py27-pexpect
# Specialized factors for py27.
- TOXENV=py27-pexpect,py27-trial,py27-numpy
- TOXENV=py27-nobyte
- TOXENV=py27-xdist
- TOXENV=py27-trial
- TOXENV=py27-numpy
- TOXENV=py27-pluggymaster PYTEST_NO_COVERAGE=1
- TOXENV=py36-pexpect
# Specialized factors for py36.
- TOXENV=py36-pexpect,py36-trial,py36-numpy
- TOXENV=py36-xdist
- TOXENV=py36-trial
- TOXENV=py36-numpy
- TOXENV=py36-pluggymaster PYTEST_NO_COVERAGE=1
- TOXENV=py27-nobyte

jobs:
include:
Expand Down
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -211,6 +211,7 @@ Thomas Hisch
Tim Strazny
Tom Dalton
Tom Viner
Tomer Keren
Trevor Bekolay
Tyler Goodlet
Tzu-ping Chung
Expand Down
41 changes: 41 additions & 0 deletions CONTRIBUTING.rst
Expand Up @@ -280,6 +280,47 @@ Here is a simple overview, with pytest-specific bits:
base: features # if it's a feature


Writing Tests
----------------------------

Writing tests for plugins or for pytest itself is often done using the `testdir fixture <https://docs.pytest.org/en/latest/reference.html#testdir>`_, as a "black-box" test.

For example, to ensure a simple test passes you can write:

.. code-block:: python
def test_true_assertion(testdir):
testdir.makepyfile(
"""
def test_foo():
assert True
"""
)
result = testdir.runpytest()
result.assert_outcomes(failed=0, passed=1)
Alternatively, it is possible to make checks based on the actual output of the termal using
*glob-like* expressions:

.. code-block:: python
def test_true_assertion(testdir):
testdir.makepyfile(
"""
def test_foo():
assert False
"""
)
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*assert False*", "*1 failed*"])
When choosing a file where to write a new test, take a look at the existing files and see if there's
one file which looks like a good fit. For example, a regression test about a bug in the ``--lf`` option
should go into ``test_cacheprovider.py``, given that this option is implemented in ``cacheprovider.py``.
If in doubt, go ahead and open a PR with your best guess and we can discuss this over the code.


Joining the Development Team
----------------------------

Expand Down
26 changes: 14 additions & 12 deletions appveyor.yml
@@ -1,27 +1,29 @@
environment:
matrix:
- TOXENV: "linting,docs,doctesting"
PYTEST_NO_COVERAGE: "1"
- TOXENV: "py27"
- TOXENV: "py34"
- TOXENV: "py35"
- TOXENV: "py36"
- TOXENV: "py37"
PYTEST_NO_COVERAGE: "1"
- TOXENV: "linting,docs,doctesting"
- TOXENV: "py36"
- TOXENV: "py35"
- TOXENV: "py34"
- TOXENV: "pypy"
PYTEST_NO_COVERAGE: "1"
- TOXENV: "py27-xdist"
- TOXENV: "py27-trial"
- TOXENV: "py27-numpy"
# Specialized factors for py27.
- TOXENV: "py27-trial,py27-numpy,py27-nobyte"
- TOXENV: "py27-pluggymaster"
PYTEST_NO_COVERAGE: "1"
- TOXENV: "py36-xdist"
- TOXENV: "py36-trial"
- TOXENV: "py36-numpy"
- TOXENV: "py27-xdist"
# Specialized factors for py36.
- TOXENV: "py36-trial,py36-numpy"
- TOXENV: "py36-pluggymaster"
PYTEST_NO_COVERAGE: "1"
- TOXENV: "py27-nobyte"
- TOXENV: "py36-freeze"
PYTEST_NO_COVERAGE: "1"
- TOXENV: "py36-xdist"

matrix:
fast_finish: true

install:
- echo Installed Pythons
Expand Down
1 change: 1 addition & 0 deletions changelog/4063.trivial.rst
@@ -0,0 +1 @@
Exclude 0.00 second entries from ``--duration`` output unless ``-vv`` is passed on the command-line.
1 change: 1 addition & 0 deletions changelog/4132.bugfix.rst
@@ -0,0 +1 @@
Fix duplicate printing of internal errors when using ``--pdb``.
1 change: 1 addition & 0 deletions changelog/4151.doc.rst
@@ -0,0 +1 @@
Add tempir testing example to CONTRIBUTING.rst guide
1 change: 1 addition & 0 deletions changelog/4152.bugfix.rst
@@ -0,0 +1 @@
Display the filename when encountering ``SyntaxWarning``.
2 changes: 1 addition & 1 deletion doc/en/deprecations.rst
Expand Up @@ -304,7 +304,7 @@ This form of test function doesn't support fixtures properly, and users should s
.. code-block:: python
@pytest.mark.parametrize("x, y", [(2, 4), (3, 9)])
def test_squared():
def test_squared(x, y):
assert x ** x == y
Expand Down
1 change: 1 addition & 0 deletions doc/en/usage.rst
Expand Up @@ -269,6 +269,7 @@ To get a list of the slowest 10 test durations::

pytest --durations=10

By default, pytest will not show test durations that are too small (<0.01s) unless ``-vv`` is passed on the command-line.

Creating JUnitXML format files
----------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/assertion/rewrite.py
Expand Up @@ -399,7 +399,7 @@ def _rewrite_test(config, fn):
finally:
del state._indecode
try:
tree = ast.parse(source)
tree = ast.parse(source, filename=fn.strpath)
except SyntaxError:
# Let this pop up again in the real import.
state.trace("failed to parse: %r" % (fn,))
Expand Down
11 changes: 6 additions & 5 deletions src/_pytest/debugging.py
@@ -1,10 +1,12 @@
""" interactive debugging with PDB, the Python Debugger. """
from __future__ import absolute_import, division, print_function

import os
import pdb
import sys
import os
from doctest import UnexpectedException

from _pytest import outcomes
from _pytest.config import hookimpl

try:
Expand Down Expand Up @@ -109,9 +111,6 @@ def pytest_exception_interact(self, node, call, report):
_enter_pdb(node, call.excinfo, report)

def pytest_internalerror(self, excrepr, excinfo):
for line in str(excrepr).split("\n"):
sys.stderr.write("INTERNALERROR> %s\n" % line)
sys.stderr.flush()
tb = _postmortem_traceback(excinfo)
post_mortem(tb)

Expand Down Expand Up @@ -164,8 +163,9 @@ def _enter_pdb(node, excinfo, rep):
rep.toterminal(tw)
tw.sep(">", "entering PDB")
tb = _postmortem_traceback(excinfo)
post_mortem(tb)
rep._pdbshown = True
if post_mortem(tb):
outcomes.exit("Quitting debugger")
return rep


Expand Down Expand Up @@ -196,3 +196,4 @@ def get_stack(self, f, t):
p = Pdb()
p.reset()
p.interaction(None, t)
return p.quitting
5 changes: 2 additions & 3 deletions src/_pytest/fixtures.py
Expand Up @@ -1020,7 +1020,7 @@ class FixtureFunctionMarker(object):

def __call__(self, function):
if isclass(function):
raise ValueError("class fixtures not supported (may be in the future)")
raise ValueError("class fixtures not supported (maybe in the future)")

if getattr(function, "_pytestfixturefunction", False):
raise ValueError(
Expand Down Expand Up @@ -1371,8 +1371,7 @@ def getfixturedefs(self, argname, nodeid):
fixturedefs = self._arg2fixturedefs[argname]
except KeyError:
return None
else:
return tuple(self._matchfactories(fixturedefs, nodeid))
return tuple(self._matchfactories(fixturedefs, nodeid))

def _matchfactories(self, fixturedefs, nodeid):
for fixturedef in fixturedefs:
Expand Down
7 changes: 2 additions & 5 deletions src/_pytest/main.py
Expand Up @@ -570,9 +570,7 @@ def _recurse(self, path):
return True

def _tryconvertpyarg(self, x):
"""Convert a dotted module name to path.
"""
"""Convert a dotted module name to path."""
try:
with _patched_find_module():
loader = pkgutil.find_loader(x)
Expand Down Expand Up @@ -604,8 +602,7 @@ def _parsearg(self, arg):
raise UsageError(
"file or package not found: " + arg + " (missing __init__.py?)"
)
else:
raise UsageError("file not found: " + arg)
raise UsageError("file not found: " + arg)
parts[0] = path
return parts

Expand Down
4 changes: 2 additions & 2 deletions src/_pytest/pytester.py
Expand Up @@ -17,7 +17,7 @@

from _pytest.capture import MultiCapture, SysCapture
from _pytest._code import Source
from _pytest.main import Session, EXIT_OK
from _pytest.main import Session, EXIT_INTERRUPTED, EXIT_OK
from _pytest.assertion.rewrite import AssertionRewritingHook
from _pytest.pathlib import Path
from _pytest.compat import safe_str
Expand Down Expand Up @@ -857,7 +857,7 @@ class reprec(object):

# typically we reraise keyboard interrupts from the child run
# because it's our user requesting interruption of the testing
if ret == 2 and not kwargs.get("no_reraise_ctrlc"):
if ret == EXIT_INTERRUPTED and not kwargs.get("no_reraise_ctrlc"):
calls = reprec.getcalls("pytest_keyboard_interrupt")
if calls and calls[-1].excinfo.type == KeyboardInterrupt:
raise KeyboardInterrupt()
Expand Down
5 changes: 5 additions & 0 deletions src/_pytest/runner.py
Expand Up @@ -30,6 +30,7 @@ def pytest_addoption(parser):

def pytest_terminal_summary(terminalreporter):
durations = terminalreporter.config.option.durations
verbose = terminalreporter.config.getvalue("verbose")
if durations is None:
return
tr = terminalreporter
Expand All @@ -49,6 +50,10 @@ def pytest_terminal_summary(terminalreporter):
dlist = dlist[:durations]

for rep in dlist:
if verbose < 2 and rep.duration < 0.005:
tr.write_line("")
tr.write_line("(0.00 durations hidden. Use -vv to show these durations.)")
break
nodeid = rep.nodeid.replace("::()::", "::")
tr.write_line("%02.2fs %-8s %s" % (rep.duration, rep.when, nodeid))

Expand Down

0 comments on commit e4e4fd1

Please sign in to comment.