[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:
Raphael Collet 2014-11-13 17:40:41 +01:00
parent 2052c16d21
commit 908252ec88
4 changed files with 42 additions and 3 deletions

View File

@ -111,12 +111,10 @@ class TestACL(common.TransactionCase):
# accessing fields must no raise exceptions...
part.name
# ... 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'):
part.email
self.assertEqual(cm.exception.args[0], 'AccessError')
if __name__ == '__main__':
unittest2.main()

View File

@ -185,6 +185,9 @@ class TestNewFields(common.TransactionCase):
with self.assertRaises(Exception):
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
# messages in discussion
discussion.participants += self.env.user

View File

@ -815,6 +815,24 @@ class Environment(object):
env.computed.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):
""" Check whether `field` must be recomputed, and returns a recordset
with all records to recompute for `field`.

View File

@ -16,6 +16,7 @@ import time
import unittest2
import urllib2
import xmlrpclib
from contextlib import contextmanager
from datetime import datetime, timedelta
import werkzeug
@ -104,6 +105,20 @@ class BaseCase(unittest2.TestCase):
module, xid = xid.split('.')
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):
""" 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, {})
def tearDown(self):
# rollback and close the cursor, and reset the environments
self.env.reset()
self.cr.rollback()
self.cr.close()
@ -139,9 +156,12 @@ class SingleTransactionCase(BaseCase):
@classmethod
def tearDownClass(cls):
# rollback and close the cursor, and reset the environments
cls.env.reset()
cls.cr.rollback()
cls.cr.close()
class RedirectHandler(urllib2.HTTPRedirectHandler):
"""
HTTPRedirectHandler is predicated upon HTTPErrorProcessor being used and