[MERGE]:trunk
bzr revid: apa@tinyerp.com-20121101062629-ijwkyx123oqfrb91
This commit is contained in:
commit
251e3c974f
|
@ -87,9 +87,9 @@ In addition to the above possibilities, when invoked with a non-existing module
|
|||
sub-modules.
|
||||
|
||||
Depending on the unittest2_ class that is used to write the tests (see
|
||||
``openerp.tests.common`` for some helper classes that you can re-use), a database
|
||||
may be created before the test is run, and the module providing the test will
|
||||
be installed on that database.
|
||||
:mod:`openerp.tests.common` for some helper classes that you can re-use), a
|
||||
database may be created before the test is run, and the module providing the
|
||||
test will be installed on that database.
|
||||
|
||||
Because creating a database, installing modules, and then dropping it is
|
||||
expensive, it is possible to interleave the run of the ``fast_suite`` tests
|
||||
|
@ -98,3 +98,20 @@ each requested module is installed, its fast_suite tests are run. The database
|
|||
is thus created and dropped (and the modules installed) only once.
|
||||
|
||||
.. _unittest2: http://pypi.python.org/pypi/unittest2
|
||||
|
||||
TestCase subclasses
|
||||
-------------------
|
||||
|
||||
.. automodule:: openerp.tests.common
|
||||
:members:
|
||||
|
||||
.. note::
|
||||
|
||||
The `setUp` and `tearDown` methods are not part of the tests. Uncaught
|
||||
exceptions in those methods are errors, not test failures. In particular,
|
||||
a failing `setUp` will not be followed by a `tearDown` causing any
|
||||
allocated resource in the `setUp` to not be released by the `tearDown`.
|
||||
|
||||
In the :py:class:`openerp.tests.common.TransactionCase` and
|
||||
:py:class:`openerp.tests.common.SingleTransactionCase`, this means the
|
||||
test suite can hang because of unclosed cursors.
|
||||
|
|
|
@ -101,6 +101,7 @@ def preload_registry(dbname):
|
|||
def run_test_file(dbname, test_file):
|
||||
""" Preload a registry, possibly run a test file, and start the cron."""
|
||||
try:
|
||||
config = openerp.tools.config
|
||||
db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False)
|
||||
cr = db.cursor()
|
||||
_logger.info('loading test file %s', test_file)
|
||||
|
|
|
@ -1548,7 +1548,6 @@ class BaseModel(object):
|
|||
)
|
||||
self._invalids.update(fields)
|
||||
if error_msgs:
|
||||
cr.rollback()
|
||||
raise except_orm('ValidateError', '\n'.join(error_msgs))
|
||||
else:
|
||||
self._invalids.clear()
|
||||
|
|
|
@ -9,7 +9,7 @@ See the :ref:`test-framework` section in the :ref:`features` list.
|
|||
"""
|
||||
|
||||
from . import test_expression, test_html_sanitize, test_ir_sequence, test_orm,\
|
||||
test_per_class_teardown, \
|
||||
test_basecase, \
|
||||
test_view_validation, test_uninstall, test_misc, test_db_cursor
|
||||
|
||||
fast_suite = [
|
||||
|
@ -21,7 +21,7 @@ checks = [
|
|||
test_html_sanitize,
|
||||
test_db_cursor,
|
||||
test_orm,
|
||||
test_per_class_teardown,
|
||||
test_basecase,
|
||||
test_view_validation,
|
||||
test_misc,
|
||||
]
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
"""
|
||||
The module :mod:`openerp.tests.common` provides a few helpers and classes to write
|
||||
tests.
|
||||
"""
|
||||
import threading
|
||||
import time
|
||||
import unittest2
|
||||
|
@ -40,10 +43,11 @@ def stop_openerp():
|
|||
"""
|
||||
openerp.service.stop_services()
|
||||
|
||||
|
||||
class BaseCase(unittest2.TestCase):
|
||||
"""
|
||||
Subclass of TestCase for common OpenERP-specific code.
|
||||
|
||||
This class is abstract and expects self.cr and self.uid to be initialized by subclasses.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
|
@ -54,6 +58,29 @@ class BaseCase(unittest2.TestCase):
|
|||
def registry(self, model):
|
||||
return openerp.modules.registry.RegistryManager.get(DB)[model]
|
||||
|
||||
@classmethod
|
||||
def ref(self, xid):
|
||||
""" Returns database ID corresponding to a given identifier.
|
||||
|
||||
:param xid: fully-qualified record identifier, in the form ``module.identifier``
|
||||
:raise: ValueError if not found
|
||||
"""
|
||||
assert "." in xid, "this method requires a fully qualified parameter, in the following form: 'module.identifier'"
|
||||
module, xid = xid.split('.')
|
||||
_, id = self.registry('ir.model.data').get_object_reference(self.cr, self.uid, module, xid)
|
||||
return id
|
||||
|
||||
@classmethod
|
||||
def browse_ref(self, xid):
|
||||
""" Returns a browsable record for the given identifier.
|
||||
|
||||
:param xid: fully-qualified record identifier, in the form ``module.identifier``
|
||||
:raise: ValueError if not found
|
||||
"""
|
||||
assert "." in xid, "this method requires a fully qualified parameter, in the following form: 'module.identifier'"
|
||||
module, xid = xid.split('.')
|
||||
return self.registry('ir.model.data').get_object(self.cr, self.uid, module, xid)
|
||||
|
||||
|
||||
class TransactionCase(BaseCase):
|
||||
"""
|
||||
|
@ -92,8 +119,8 @@ class RpcCase(unittest2.TestCase):
|
|||
Subclass of TestCase with a few XML-RPC proxies.
|
||||
"""
|
||||
|
||||
def __init__(self, name):
|
||||
super(RpcCase, self).__init__(name)
|
||||
def __init__(self, methodName='runTest'):
|
||||
super(RpcCase, self).__init__(methodName)
|
||||
|
||||
class A(object):
|
||||
pass
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import unittest2
|
||||
|
||||
import openerp
|
||||
import common
|
||||
|
||||
class test_per_class_teardown(common.SingleTransactionCase):
|
||||
class test_single_transaction_case(common.SingleTransactionCase):
|
||||
"""
|
||||
Check the whole-class transaction behavior of SingleTransactionCase.
|
||||
"""
|
||||
|
@ -22,7 +21,30 @@ class test_per_class_teardown(common.SingleTransactionCase):
|
|||
ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
|
||||
self.assertEqual(1, len(ids), "Test partner not found.")
|
||||
|
||||
class test_per_method_teardown(common.TransactionCase):
|
||||
def test_20a(self):
|
||||
""" Create a partner with a XML ID """
|
||||
cr, uid = self.cr, self.uid
|
||||
res_partner = self.registry('res.partner')
|
||||
ir_model_data = self.registry('ir.model.data')
|
||||
pid, _ = res_partner.name_create(cr, uid, 'Mr Blue')
|
||||
ir_model_data.create(cr, uid, {'name': 'test_partner_blue',
|
||||
'module': 'base',
|
||||
'model': 'res.partner',
|
||||
'res_id': pid})
|
||||
def test_20b(self):
|
||||
""" Resolve xml id with ref() and browse_ref() """
|
||||
cr, uid = self.cr, self.uid
|
||||
res_partner = self.registry('res.partner')
|
||||
xid = 'base.test_partner_blue'
|
||||
p_ref = self.ref(xid)
|
||||
self.assertTrue(p_ref, "ref() should resolve xid to database ID")
|
||||
partner = res_partner.browse(cr, uid, p_ref)
|
||||
p_browse_ref = self.browse_ref(xid)
|
||||
self.assertEqual(partner, p_browse_ref, "browse_ref() should resolve xid to browse records")
|
||||
|
||||
|
||||
|
||||
class test_transaction_case(common.TransactionCase):
|
||||
"""
|
||||
Check the per-method transaction behavior of TransactionCase.
|
||||
"""
|
|
@ -286,8 +286,11 @@ class YamlInterpreter(object):
|
|||
model = self.get_model(record.model)
|
||||
|
||||
view_id = record.view
|
||||
if view_id and (view_id is not True):
|
||||
view_id = self.pool.get('ir.model.data').get_object_reference(self.cr, SUPERUSER_ID, self.module, record.view)[1]
|
||||
if view_id and (view_id is not True) and isinstance(view_id, basestring):
|
||||
module = self.module
|
||||
if '.' in view_id:
|
||||
module, view_id = view_id.split('.',1)
|
||||
view_id = self.pool.get('ir.model.data').get_object_reference(self.cr, SUPERUSER_ID, module, view_id)[1]
|
||||
|
||||
if model.is_transient():
|
||||
record_dict=self.create_osv_memory_record(record, fields)
|
||||
|
@ -378,7 +381,11 @@ class YamlInterpreter(object):
|
|||
return False
|
||||
return val
|
||||
|
||||
view = view_info and etree.fromstring(view_info['arch'].encode('utf-8')) or False
|
||||
if view_info:
|
||||
arch = etree.fromstring(view_info['arch'].encode('utf-8'))
|
||||
view = arch if len(arch) else False
|
||||
else:
|
||||
view = False
|
||||
fields = fields or {}
|
||||
if view is not False:
|
||||
fg = view_info['fields']
|
||||
|
|
|
@ -109,6 +109,8 @@ def assert_constructor(loader, node):
|
|||
|
||||
def record_constructor(loader, node):
|
||||
kwargs = loader.construct_mapping(node)
|
||||
assert "model" in kwargs, "'model' argument is required for !record"
|
||||
assert "id" in kwargs, "'id' argument is required for !record"
|
||||
return Record(**kwargs)
|
||||
|
||||
def python_constructor(loader, node):
|
||||
|
|
Loading…
Reference in New Issue