get py.test to run at least basically on top of jython
* allow and document calling of monkeypatch.undo() from a test * default to 'sys' on platforms there no 'os.dup' is available * use "compile" to perform "tryparsing" checks --HG-- branch : trunk
This commit is contained in:
parent
7ab98c1b25
commit
783c714a2c
|
@ -157,14 +157,13 @@ class Source(object):
|
|||
""" return True if source is parseable, heuristically
|
||||
deindenting it by default.
|
||||
"""
|
||||
import parser
|
||||
if deindent:
|
||||
source = str(self.deindent())
|
||||
else:
|
||||
source = str(self)
|
||||
try:
|
||||
parser.suite(source+'\n')
|
||||
except (parser.ParserError, SyntaxError):
|
||||
compile(source+'\n', "x", "exec")
|
||||
except SyntaxError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
|
|
@ -85,6 +85,7 @@ argument which offers the same interface.
|
|||
"""
|
||||
|
||||
import py
|
||||
import os
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
|
@ -131,11 +132,15 @@ class CaptureManager:
|
|||
|
||||
def _getmethod(self, config, fspath):
|
||||
if config.option.capture:
|
||||
return config.option.capture
|
||||
method = config.option.capture
|
||||
else:
|
||||
try:
|
||||
return config._conftest.rget("option_capture", path=fspath)
|
||||
method = config._conftest.rget("option_capture", path=fspath)
|
||||
except KeyError:
|
||||
return "fd"
|
||||
method = "fd"
|
||||
if method == "fd" and not hasattr(os, 'dup'): # e.g. jython
|
||||
method = "sys"
|
||||
return method
|
||||
|
||||
def resumecapture_item(self, item):
|
||||
method = self._getmethod(item.config, item.fspath)
|
||||
|
|
|
@ -4,8 +4,8 @@ safely patch object attributes, dicts and environment variables.
|
|||
Usage
|
||||
----------------
|
||||
|
||||
Use the `monkeypatch funcarg`_ to safely patch environment
|
||||
variables, object attributes or dictionaries. For example, if you want
|
||||
Use the `monkeypatch funcarg`_ to safely modify or delete environment
|
||||
variables, object attributes or dictionary values. For example, if you want
|
||||
to set the environment variable ``ENV1`` and patch the
|
||||
``os.path.abspath`` function to return a particular value during a test
|
||||
function execution you can write it down like this:
|
||||
|
@ -31,6 +31,20 @@ can use this example:
|
|||
monkeypatch.setenv('PATH', 'x/y', prepend=":")
|
||||
# x/y will be at the beginning of $PATH
|
||||
|
||||
calling "undo" finalization explicitely
|
||||
-----------------------------------------
|
||||
|
||||
Usually at the end of function execution py.test will invoke
|
||||
a teardown hook which undoes the changes. If you cannot wait
|
||||
that long you can also call finalization explicitely::
|
||||
|
||||
monkeypatch.undo()
|
||||
|
||||
This will undo previous changes. This call consumes the
|
||||
undo stack. Calling it a second time has no effect.
|
||||
Within a test you can continue to use the monkeypatch
|
||||
object, however.
|
||||
|
||||
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||
"""
|
||||
|
||||
|
@ -54,7 +68,7 @@ def pytest_funcarg__monkeypatch(request):
|
|||
deletion has no target.
|
||||
"""
|
||||
monkeypatch = MonkeyPatch()
|
||||
request.addfinalizer(monkeypatch.finalize)
|
||||
request.addfinalizer(monkeypatch.undo)
|
||||
return monkeypatch
|
||||
|
||||
notset = object()
|
||||
|
@ -97,17 +111,19 @@ class MonkeyPatch:
|
|||
def delenv(self, name, raising=True):
|
||||
self.delitem(os.environ, name, raising=raising)
|
||||
|
||||
def finalize(self):
|
||||
def undo(self):
|
||||
for obj, name, value in self._setattr:
|
||||
if value is not notset:
|
||||
setattr(obj, name, value)
|
||||
else:
|
||||
delattr(obj, name)
|
||||
self._setattr[:] = []
|
||||
for dictionary, name, value in self._setitem:
|
||||
if value is notset:
|
||||
del dictionary[name]
|
||||
else:
|
||||
dictionary[name] = value
|
||||
self._setitem[:] = []
|
||||
|
||||
|
||||
def test_setattr():
|
||||
|
@ -118,12 +134,16 @@ def test_setattr():
|
|||
assert A.x == 2
|
||||
monkeypatch.setattr(A, 'x', 3)
|
||||
assert A.x == 3
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert A.x == 1
|
||||
|
||||
A.x = 5
|
||||
monkeypatch.undo() # double-undo makes no modification
|
||||
assert A.x == 5
|
||||
|
||||
monkeypatch.setattr(A, 'y', 3)
|
||||
assert A.y == 3
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert not hasattr(A, 'y')
|
||||
|
||||
def test_delattr():
|
||||
|
@ -132,7 +152,7 @@ def test_delattr():
|
|||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.delattr(A, 'x')
|
||||
assert not hasattr(A, 'x')
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert A.x == 1
|
||||
|
||||
monkeypatch = MonkeyPatch()
|
||||
|
@ -141,7 +161,7 @@ def test_delattr():
|
|||
monkeypatch.delattr(A, 'y', raising=False)
|
||||
monkeypatch.setattr(A, 'x', 5)
|
||||
assert A.x == 5
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert A.x == 1
|
||||
|
||||
def test_setitem():
|
||||
|
@ -153,9 +173,12 @@ def test_setitem():
|
|||
assert d['y'] == 1700
|
||||
monkeypatch.setitem(d, 'x', 3)
|
||||
assert d['x'] == 3
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert d['x'] == 1
|
||||
assert 'y' not in d
|
||||
d['x'] = 5
|
||||
monkeypatch.undo()
|
||||
assert d['x'] == 5
|
||||
|
||||
def test_delitem():
|
||||
d = {'x': 1}
|
||||
|
@ -170,7 +193,7 @@ def test_delitem():
|
|||
d['hello'] = 'world'
|
||||
monkeypatch.setitem(d, 'x', 1500)
|
||||
assert d['x'] == 1500
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert d == {'hello': 'world', 'x': 1}
|
||||
|
||||
def test_setenv():
|
||||
|
@ -178,7 +201,7 @@ def test_setenv():
|
|||
monkeypatch.setenv('XYZ123', 2)
|
||||
import os
|
||||
assert os.environ['XYZ123'] == "2"
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert 'XYZ123' not in os.environ
|
||||
|
||||
def test_delenv():
|
||||
|
@ -187,7 +210,7 @@ def test_delenv():
|
|||
monkeypatch = MonkeyPatch()
|
||||
py.test.raises(KeyError, "monkeypatch.delenv(%r, raising=True)" % name)
|
||||
monkeypatch.delenv(name, raising=False)
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
os.environ[name] = "1"
|
||||
try:
|
||||
monkeypatch = MonkeyPatch()
|
||||
|
@ -195,7 +218,7 @@ def test_delenv():
|
|||
assert name not in os.environ
|
||||
monkeypatch.setenv(name, "3")
|
||||
assert os.environ[name] == "3"
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert os.environ[name] == "1"
|
||||
finally:
|
||||
if name in os.environ:
|
||||
|
@ -208,7 +231,7 @@ def test_setenv_prepend():
|
|||
assert os.environ['XYZ123'] == "2"
|
||||
monkeypatch.setenv('XYZ123', 3, prepend="-")
|
||||
assert os.environ['XYZ123'] == "3-2"
|
||||
monkeypatch.finalize()
|
||||
monkeypatch.undo()
|
||||
assert 'XYZ123' not in os.environ
|
||||
|
||||
def test_monkeypatch_plugin(testdir):
|
||||
|
|
|
@ -2,6 +2,16 @@ import py, os, sys
|
|||
from py.__.test.plugin.pytest_capture import CaptureManager
|
||||
|
||||
class TestCaptureManager:
|
||||
def test_getmethod_default_no_fd(self, testdir, monkeypatch):
|
||||
config = testdir.parseconfig(testdir.tmpdir)
|
||||
assert config.getvalue("capture") is None
|
||||
capman = CaptureManager()
|
||||
monkeypatch.delattr(os, 'dup')
|
||||
try:
|
||||
assert capman._getmethod(config, None) == "sys"
|
||||
finally:
|
||||
monkeypatch.finalize()
|
||||
|
||||
def test_configure_per_fspath(self, testdir):
|
||||
config = testdir.parseconfig(testdir.tmpdir)
|
||||
assert config.getvalue("capture") is None
|
||||
|
|
Loading…
Reference in New Issue