[FIX] tests: make sure that a failed tests does not leave the environment dirty
When a failure occurs, or when exiting an assertRaises(), the environment should not contain fields to recompute.
This commit is contained in:
parent
2052c16d21
commit
908252ec88
|
@ -111,12 +111,10 @@ class TestACL(common.TransactionCase):
|
||||||
# accessing fields must no raise exceptions...
|
# accessing fields must no raise exceptions...
|
||||||
part.name
|
part.name
|
||||||
# ... except if they are restricted
|
# ... except if they are restricted
|
||||||
with self.assertRaises(openerp.osv.orm.except_orm) as cm:
|
with self.assertRaises(openerp.exceptions.AccessError):
|
||||||
with mute_logger('openerp.models'):
|
with mute_logger('openerp.models'):
|
||||||
part.email
|
part.email
|
||||||
|
|
||||||
self.assertEqual(cm.exception.args[0], 'AccessError')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest2.main()
|
unittest2.main()
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,9 @@ class TestNewFields(common.TransactionCase):
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
self.env['test_new_api.message'].create({'discussion': discussion.id, 'body': 'Whatever'})
|
self.env['test_new_api.message'].create({'discussion': discussion.id, 'body': 'Whatever'})
|
||||||
|
|
||||||
|
# make sure that assertRaises() does not leave fields to recompute
|
||||||
|
self.assertFalse(self.env.has_todo())
|
||||||
|
|
||||||
# put back oneself into discussion participants: now we can create
|
# put back oneself into discussion participants: now we can create
|
||||||
# messages in discussion
|
# messages in discussion
|
||||||
discussion.participants += self.env.user
|
discussion.participants += self.env.user
|
||||||
|
|
|
@ -815,6 +815,24 @@ class Environment(object):
|
||||||
env.computed.clear()
|
env.computed.clear()
|
||||||
env.dirty.clear()
|
env.dirty.clear()
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
""" Clear all record caches, and discard all fields to recompute.
|
||||||
|
This may be useful when recovering from a failed ORM operation.
|
||||||
|
"""
|
||||||
|
self.invalidate_all()
|
||||||
|
self.all.todo.clear()
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def clear_upon_failure(self):
|
||||||
|
""" Context manager that clears the environments (caches and fields to
|
||||||
|
recompute) upon exception.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
except Exception:
|
||||||
|
self.clear()
|
||||||
|
raise
|
||||||
|
|
||||||
def field_todo(self, field):
|
def field_todo(self, field):
|
||||||
""" Check whether `field` must be recomputed, and returns a recordset
|
""" Check whether `field` must be recomputed, and returns a recordset
|
||||||
with all records to recompute for `field`.
|
with all records to recompute for `field`.
|
||||||
|
|
|
@ -16,6 +16,7 @@ import time
|
||||||
import unittest2
|
import unittest2
|
||||||
import urllib2
|
import urllib2
|
||||||
import xmlrpclib
|
import xmlrpclib
|
||||||
|
from contextlib import contextmanager
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
@ -104,6 +105,20 @@ class BaseCase(unittest2.TestCase):
|
||||||
module, xid = xid.split('.')
|
module, xid = xid.split('.')
|
||||||
return self.registry('ir.model.data').get_object(self.cr, self.uid, module, xid)
|
return self.registry('ir.model.data').get_object(self.cr, self.uid, module, xid)
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def _assertRaises(self, exception):
|
||||||
|
""" Context manager that clears the environment upon failure. """
|
||||||
|
with super(BaseCase, self).assertRaises(exception):
|
||||||
|
with self.env.clear_upon_failure():
|
||||||
|
yield
|
||||||
|
|
||||||
|
def assertRaises(self, exception, func=None, *args, **kwargs):
|
||||||
|
if func:
|
||||||
|
with self._assertRaises(exception):
|
||||||
|
func(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
return self._assertRaises(exception)
|
||||||
|
|
||||||
|
|
||||||
class TransactionCase(BaseCase):
|
class TransactionCase(BaseCase):
|
||||||
""" TestCase in which each test method is run in its own transaction,
|
""" TestCase in which each test method is run in its own transaction,
|
||||||
|
@ -120,6 +135,8 @@ class TransactionCase(BaseCase):
|
||||||
self.env = api.Environment(self.cr, self.uid, {})
|
self.env = api.Environment(self.cr, self.uid, {})
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
# rollback and close the cursor, and reset the environments
|
||||||
|
self.env.reset()
|
||||||
self.cr.rollback()
|
self.cr.rollback()
|
||||||
self.cr.close()
|
self.cr.close()
|
||||||
|
|
||||||
|
@ -139,9 +156,12 @@ class SingleTransactionCase(BaseCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
|
# rollback and close the cursor, and reset the environments
|
||||||
|
cls.env.reset()
|
||||||
cls.cr.rollback()
|
cls.cr.rollback()
|
||||||
cls.cr.close()
|
cls.cr.close()
|
||||||
|
|
||||||
|
|
||||||
class RedirectHandler(urllib2.HTTPRedirectHandler):
|
class RedirectHandler(urllib2.HTTPRedirectHandler):
|
||||||
"""
|
"""
|
||||||
HTTPRedirectHandler is predicated upon HTTPErrorProcessor being used and
|
HTTPRedirectHandler is predicated upon HTTPErrorProcessor being used and
|
||||||
|
|
Loading…
Reference in New Issue