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
|
@ -11,6 +11,7 @@ syntax:glob
|
||||||
*.pyo
|
*.pyo
|
||||||
*.swp
|
*.swp
|
||||||
*.html
|
*.html
|
||||||
|
*.class
|
||||||
|
|
||||||
build/
|
build/
|
||||||
py.egg-info
|
py.egg-info
|
||||||
|
|
|
@ -157,14 +157,13 @@ class Source(object):
|
||||||
""" return True if source is parseable, heuristically
|
""" return True if source is parseable, heuristically
|
||||||
deindenting it by default.
|
deindenting it by default.
|
||||||
"""
|
"""
|
||||||
import parser
|
|
||||||
if deindent:
|
if deindent:
|
||||||
source = str(self.deindent())
|
source = str(self.deindent())
|
||||||
else:
|
else:
|
||||||
source = str(self)
|
source = str(self)
|
||||||
try:
|
try:
|
||||||
parser.suite(source+'\n')
|
compile(source+'\n', "x", "exec")
|
||||||
except (parser.ParserError, SyntaxError):
|
except SyntaxError:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -85,6 +85,7 @@ argument which offers the same interface.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
import os
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
group = parser.getgroup("general")
|
group = parser.getgroup("general")
|
||||||
|
@ -131,11 +132,15 @@ class CaptureManager:
|
||||||
|
|
||||||
def _getmethod(self, config, fspath):
|
def _getmethod(self, config, fspath):
|
||||||
if config.option.capture:
|
if config.option.capture:
|
||||||
return config.option.capture
|
method = config.option.capture
|
||||||
try:
|
else:
|
||||||
return config._conftest.rget("option_capture", path=fspath)
|
try:
|
||||||
except KeyError:
|
method = config._conftest.rget("option_capture", path=fspath)
|
||||||
return "fd"
|
except KeyError:
|
||||||
|
method = "fd"
|
||||||
|
if method == "fd" and not hasattr(os, 'dup'): # e.g. jython
|
||||||
|
method = "sys"
|
||||||
|
return method
|
||||||
|
|
||||||
def resumecapture_item(self, item):
|
def resumecapture_item(self, item):
|
||||||
method = self._getmethod(item.config, item.fspath)
|
method = self._getmethod(item.config, item.fspath)
|
||||||
|
|
|
@ -4,8 +4,8 @@ safely patch object attributes, dicts and environment variables.
|
||||||
Usage
|
Usage
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Use the `monkeypatch funcarg`_ to safely patch environment
|
Use the `monkeypatch funcarg`_ to safely modify or delete environment
|
||||||
variables, object attributes or dictionaries. For example, if you want
|
variables, object attributes or dictionary values. For example, if you want
|
||||||
to set the environment variable ``ENV1`` and patch the
|
to set the environment variable ``ENV1`` and patch the
|
||||||
``os.path.abspath`` function to return a particular value during a test
|
``os.path.abspath`` function to return a particular value during a test
|
||||||
function execution you can write it down like this:
|
function execution you can write it down like this:
|
||||||
|
@ -31,6 +31,20 @@ can use this example:
|
||||||
monkeypatch.setenv('PATH', 'x/y', prepend=":")
|
monkeypatch.setenv('PATH', 'x/y', prepend=":")
|
||||||
# x/y will be at the beginning of $PATH
|
# 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/
|
.. _`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.
|
deletion has no target.
|
||||||
"""
|
"""
|
||||||
monkeypatch = MonkeyPatch()
|
monkeypatch = MonkeyPatch()
|
||||||
request.addfinalizer(monkeypatch.finalize)
|
request.addfinalizer(monkeypatch.undo)
|
||||||
return monkeypatch
|
return monkeypatch
|
||||||
|
|
||||||
notset = object()
|
notset = object()
|
||||||
|
@ -97,17 +111,19 @@ class MonkeyPatch:
|
||||||
def delenv(self, name, raising=True):
|
def delenv(self, name, raising=True):
|
||||||
self.delitem(os.environ, name, raising=raising)
|
self.delitem(os.environ, name, raising=raising)
|
||||||
|
|
||||||
def finalize(self):
|
def undo(self):
|
||||||
for obj, name, value in self._setattr:
|
for obj, name, value in self._setattr:
|
||||||
if value is not notset:
|
if value is not notset:
|
||||||
setattr(obj, name, value)
|
setattr(obj, name, value)
|
||||||
else:
|
else:
|
||||||
delattr(obj, name)
|
delattr(obj, name)
|
||||||
|
self._setattr[:] = []
|
||||||
for dictionary, name, value in self._setitem:
|
for dictionary, name, value in self._setitem:
|
||||||
if value is notset:
|
if value is notset:
|
||||||
del dictionary[name]
|
del dictionary[name]
|
||||||
else:
|
else:
|
||||||
dictionary[name] = value
|
dictionary[name] = value
|
||||||
|
self._setitem[:] = []
|
||||||
|
|
||||||
|
|
||||||
def test_setattr():
|
def test_setattr():
|
||||||
|
@ -118,12 +134,16 @@ def test_setattr():
|
||||||
assert A.x == 2
|
assert A.x == 2
|
||||||
monkeypatch.setattr(A, 'x', 3)
|
monkeypatch.setattr(A, 'x', 3)
|
||||||
assert A.x == 3
|
assert A.x == 3
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert A.x == 1
|
assert A.x == 1
|
||||||
|
|
||||||
|
A.x = 5
|
||||||
|
monkeypatch.undo() # double-undo makes no modification
|
||||||
|
assert A.x == 5
|
||||||
|
|
||||||
monkeypatch.setattr(A, 'y', 3)
|
monkeypatch.setattr(A, 'y', 3)
|
||||||
assert A.y == 3
|
assert A.y == 3
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert not hasattr(A, 'y')
|
assert not hasattr(A, 'y')
|
||||||
|
|
||||||
def test_delattr():
|
def test_delattr():
|
||||||
|
@ -132,7 +152,7 @@ def test_delattr():
|
||||||
monkeypatch = MonkeyPatch()
|
monkeypatch = MonkeyPatch()
|
||||||
monkeypatch.delattr(A, 'x')
|
monkeypatch.delattr(A, 'x')
|
||||||
assert not hasattr(A, 'x')
|
assert not hasattr(A, 'x')
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert A.x == 1
|
assert A.x == 1
|
||||||
|
|
||||||
monkeypatch = MonkeyPatch()
|
monkeypatch = MonkeyPatch()
|
||||||
|
@ -141,7 +161,7 @@ def test_delattr():
|
||||||
monkeypatch.delattr(A, 'y', raising=False)
|
monkeypatch.delattr(A, 'y', raising=False)
|
||||||
monkeypatch.setattr(A, 'x', 5)
|
monkeypatch.setattr(A, 'x', 5)
|
||||||
assert A.x == 5
|
assert A.x == 5
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert A.x == 1
|
assert A.x == 1
|
||||||
|
|
||||||
def test_setitem():
|
def test_setitem():
|
||||||
|
@ -153,9 +173,12 @@ def test_setitem():
|
||||||
assert d['y'] == 1700
|
assert d['y'] == 1700
|
||||||
monkeypatch.setitem(d, 'x', 3)
|
monkeypatch.setitem(d, 'x', 3)
|
||||||
assert d['x'] == 3
|
assert d['x'] == 3
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert d['x'] == 1
|
assert d['x'] == 1
|
||||||
assert 'y' not in d
|
assert 'y' not in d
|
||||||
|
d['x'] = 5
|
||||||
|
monkeypatch.undo()
|
||||||
|
assert d['x'] == 5
|
||||||
|
|
||||||
def test_delitem():
|
def test_delitem():
|
||||||
d = {'x': 1}
|
d = {'x': 1}
|
||||||
|
@ -170,7 +193,7 @@ def test_delitem():
|
||||||
d['hello'] = 'world'
|
d['hello'] = 'world'
|
||||||
monkeypatch.setitem(d, 'x', 1500)
|
monkeypatch.setitem(d, 'x', 1500)
|
||||||
assert d['x'] == 1500
|
assert d['x'] == 1500
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert d == {'hello': 'world', 'x': 1}
|
assert d == {'hello': 'world', 'x': 1}
|
||||||
|
|
||||||
def test_setenv():
|
def test_setenv():
|
||||||
|
@ -178,7 +201,7 @@ def test_setenv():
|
||||||
monkeypatch.setenv('XYZ123', 2)
|
monkeypatch.setenv('XYZ123', 2)
|
||||||
import os
|
import os
|
||||||
assert os.environ['XYZ123'] == "2"
|
assert os.environ['XYZ123'] == "2"
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert 'XYZ123' not in os.environ
|
assert 'XYZ123' not in os.environ
|
||||||
|
|
||||||
def test_delenv():
|
def test_delenv():
|
||||||
|
@ -187,7 +210,7 @@ def test_delenv():
|
||||||
monkeypatch = MonkeyPatch()
|
monkeypatch = MonkeyPatch()
|
||||||
py.test.raises(KeyError, "monkeypatch.delenv(%r, raising=True)" % name)
|
py.test.raises(KeyError, "monkeypatch.delenv(%r, raising=True)" % name)
|
||||||
monkeypatch.delenv(name, raising=False)
|
monkeypatch.delenv(name, raising=False)
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
os.environ[name] = "1"
|
os.environ[name] = "1"
|
||||||
try:
|
try:
|
||||||
monkeypatch = MonkeyPatch()
|
monkeypatch = MonkeyPatch()
|
||||||
|
@ -195,7 +218,7 @@ def test_delenv():
|
||||||
assert name not in os.environ
|
assert name not in os.environ
|
||||||
monkeypatch.setenv(name, "3")
|
monkeypatch.setenv(name, "3")
|
||||||
assert os.environ[name] == "3"
|
assert os.environ[name] == "3"
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert os.environ[name] == "1"
|
assert os.environ[name] == "1"
|
||||||
finally:
|
finally:
|
||||||
if name in os.environ:
|
if name in os.environ:
|
||||||
|
@ -208,7 +231,7 @@ def test_setenv_prepend():
|
||||||
assert os.environ['XYZ123'] == "2"
|
assert os.environ['XYZ123'] == "2"
|
||||||
monkeypatch.setenv('XYZ123', 3, prepend="-")
|
monkeypatch.setenv('XYZ123', 3, prepend="-")
|
||||||
assert os.environ['XYZ123'] == "3-2"
|
assert os.environ['XYZ123'] == "3-2"
|
||||||
monkeypatch.finalize()
|
monkeypatch.undo()
|
||||||
assert 'XYZ123' not in os.environ
|
assert 'XYZ123' not in os.environ
|
||||||
|
|
||||||
def test_monkeypatch_plugin(testdir):
|
def test_monkeypatch_plugin(testdir):
|
||||||
|
|
|
@ -2,6 +2,16 @@ import py, os, sys
|
||||||
from py.__.test.plugin.pytest_capture import CaptureManager
|
from py.__.test.plugin.pytest_capture import CaptureManager
|
||||||
|
|
||||||
class TestCaptureManager:
|
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):
|
def test_configure_per_fspath(self, testdir):
|
||||||
config = testdir.parseconfig(testdir.tmpdir)
|
config = testdir.parseconfig(testdir.tmpdir)
|
||||||
assert config.getvalue("capture") is None
|
assert config.getvalue("capture") is None
|
||||||
|
|
Loading…
Reference in New Issue