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:
holger krekel 2009-09-05 16:54:52 +02:00
parent 7ab98c1b25
commit 783c714a2c
5 changed files with 60 additions and 22 deletions

View File

@ -11,6 +11,7 @@ syntax:glob
*.pyo
*.swp
*.html
*.class
build/
py.egg-info

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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