pytester: typing

This commit is contained in:
Daniel Hahler 2019-10-22 00:05:02 +02:00
parent cbc39dd86e
commit 886a3ad609
2 changed files with 52 additions and 21 deletions

View File

@ -11,6 +11,7 @@ import traceback
from collections.abc import Sequence
from fnmatch import fnmatch
from io import StringIO
from typing import Union
from weakref import WeakKeyDictionary
import py
@ -362,9 +363,9 @@ class RunResult:
:ivar duration: duration in seconds
"""
def __init__(self, ret, outlines, errlines, duration):
def __init__(self, ret: Union[int, ExitCode], outlines, errlines, duration) -> None:
try:
self.ret = pytest.ExitCode(ret)
self.ret = pytest.ExitCode(ret) # type: Union[int, ExitCode]
except ValueError:
self.ret = ret
self.outlines = outlines
@ -483,11 +484,7 @@ class Testdir:
self._sys_modules_snapshot = self.__take_sys_modules_snapshot()
self.chdir()
self.request.addfinalizer(self.finalize)
method = self.request.config.getoption("--runpytest")
if method == "inprocess":
self._runpytest_method = self.runpytest_inprocess
elif method == "subprocess":
self._runpytest_method = self.runpytest_subprocess
self._method = self.request.config.getoption("--runpytest")
mp = self.monkeypatch = MonkeyPatch()
mp.setenv("PYTEST_DEBUG_TEMPROOT", str(self.test_tmproot))
@ -835,7 +832,7 @@ class Testdir:
reprec = rec.pop()
else:
class reprec:
class reprec: # type: ignore
pass
reprec.ret = ret
@ -851,7 +848,7 @@ class Testdir:
for finalizer in finalizers:
finalizer()
def runpytest_inprocess(self, *args, **kwargs):
def runpytest_inprocess(self, *args, **kwargs) -> RunResult:
"""Return result of running pytest in-process, providing a similar
interface to what self.runpytest() provides.
"""
@ -866,15 +863,20 @@ class Testdir:
try:
reprec = self.inline_run(*args, **kwargs)
except SystemExit as e:
ret = e.args[0]
try:
ret = ExitCode(e.args[0])
except ValueError:
pass
class reprec:
ret = e.args[0]
class reprec: # type: ignore
ret = ret
except Exception:
traceback.print_exc()
class reprec:
ret = 3
class reprec: # type: ignore
ret = ExitCode(3)
finally:
out, err = capture.readouterr()
@ -885,16 +887,20 @@ class Testdir:
res = RunResult(
reprec.ret, out.splitlines(), err.splitlines(), time.time() - now
)
res.reprec = reprec
res.reprec = reprec # type: ignore
return res
def runpytest(self, *args, **kwargs):
def runpytest(self, *args, **kwargs) -> RunResult:
"""Run pytest inline or in a subprocess, depending on the command line
option "--runpytest" and return a :py:class:`RunResult`.
"""
args = self._ensure_basetemp(args)
return self._runpytest_method(*args, **kwargs)
if self._method == "inprocess":
return self.runpytest_inprocess(*args, **kwargs)
elif self._method == "subprocess":
return self.runpytest_subprocess(*args, **kwargs)
raise RuntimeError("Unrecognized runpytest option: {}".format(self._method))
def _ensure_basetemp(self, args):
args = list(args)
@ -1051,7 +1057,7 @@ class Testdir:
return popen
def run(self, *cmdargs, timeout=None, stdin=CLOSE_STDIN):
def run(self, *cmdargs, timeout=None, stdin=CLOSE_STDIN) -> RunResult:
"""Run a command with arguments.
Run a process using subprocess.Popen saving the stdout and stderr.
@ -1069,9 +1075,9 @@ class Testdir:
"""
__tracebackhide__ = True
cmdargs = [
cmdargs = tuple(
str(arg) if isinstance(arg, py.path.local) else arg for arg in cmdargs
]
)
p1 = self.tmpdir.join("stdout")
p2 = self.tmpdir.join("stderr")
print("running:", *cmdargs)
@ -1122,6 +1128,10 @@ class Testdir:
f2.close()
self._dump_lines(out, sys.stdout)
self._dump_lines(err, sys.stderr)
try:
ret = ExitCode(ret)
except ValueError:
pass
return RunResult(ret, out, err, time.time() - now)
def _dump_lines(self, lines, fp):
@ -1134,7 +1144,7 @@ class Testdir:
def _getpytestargs(self):
return sys.executable, "-mpytest"
def runpython(self, script):
def runpython(self, script) -> RunResult:
"""Run a python script using sys.executable as interpreter.
Returns a :py:class:`RunResult`.
@ -1146,7 +1156,7 @@ class Testdir:
"""Run python -c "command", return a :py:class:`RunResult`."""
return self.run(sys.executable, "-c", command)
def runpytest_subprocess(self, *args, timeout=None):
def runpytest_subprocess(self, *args, timeout=None) -> RunResult:
"""Run pytest as a subprocess with given arguments.
Any plugins added to the :py:attr:`plugins` list will be added using the

View File

@ -395,6 +395,27 @@ def test_testdir_subprocess(testdir):
assert testdir.runpytest_subprocess(testfile).ret == 0
def test_testdir_subprocess_via_runpytest_arg(testdir) -> None:
testfile = testdir.makepyfile(
"""
def test_testdir_subprocess(testdir):
import os
testfile = testdir.makepyfile(
\"""
import os
def test_one():
assert {} != os.getpid()
\""".format(os.getpid())
)
assert testdir.runpytest(testfile).ret == 0
"""
)
result = testdir.runpytest_subprocess(
"-p", "pytester", "--runpytest", "subprocess", testfile
)
assert result.ret == 0
def test_unicode_args(testdir):
result = testdir.runpytest("-k", "💩")
assert result.ret == ExitCode.NO_TESTS_COLLECTED