Skip to content

Commit

Permalink
[FIX] tests: make sure that a failed tests does not leave the environ…
Browse files Browse the repository at this point in the history
…ment dirty

When a failure occurs, or when exiting an assertRaises(), the environment
should not contain fields to recompute.
  • Loading branch information
rco-odoo committed Nov 17, 2014
1 parent 2052c16 commit 908252e
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 3 deletions.
4 changes: 1 addition & 3 deletions openerp/addons/base/tests/test_acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,10 @@ def test_fields_browse_restriction(self):
# 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()

Expand Down
3 changes: 3 additions & 0 deletions openerp/addons/test_new_api/tests/test_new_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ def test_15_constraint(self):
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
Expand Down
18 changes: 18 additions & 0 deletions openerp/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,24 @@ def invalidate_all(self):
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`.
Expand Down
20 changes: 20 additions & 0 deletions openerp/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import unittest2
import urllib2
import xmlrpclib
from contextlib import contextmanager
from datetime import datetime, timedelta

import werkzeug
Expand Down Expand Up @@ -104,6 +105,20 @@ def browse_ref(self, xid):
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,
Expand All @@ -120,6 +135,8 @@ def setUp(self):
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()

Expand All @@ -139,9 +156,12 @@ def setUpClass(cls):

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

0 comments on commit 908252e

Please sign in to comment.