merge upstream

bzr revid: chs@openerp.com-20121031132638-nc2o9v0gnonl5l7l
This commit is contained in:
Christophe Simonis 2012-10-31 14:26:38 +01:00
commit 478319c3ed
18 changed files with 226 additions and 36 deletions

View File

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

View File

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

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-02-08 00:44+0000\n"
"PO-Revision-Date: 2012-10-23 18:39+0000\n"
"PO-Revision-Date: 2012-10-25 07:14+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-10-24 04:55+0000\n"
"X-Generator: Launchpad (build 16179)\n"
"X-Launchpad-Export-Date: 2012-10-26 04:55+0000\n"
"X-Generator: Launchpad (build 16194)\n"
#. module: base
#: model:res.country,name:base.sh
@ -4520,7 +4520,7 @@ msgstr "Португалия"
#. module: base
#: model:ir.module.module,shortdesc:base.module_share
msgid "Share any Document"
msgstr "Совместный доступ r любым документам"
msgstr "Совместный доступ к любым документам"
#. module: base
#: field:ir.module.module,certificate:0

View File

@ -57,7 +57,7 @@ class ir_attachment(osv.osv):
def _search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):
ids = super(ir_attachment, self)._search(cr, uid, args, offset=offset,
limit=limit, order=order,
context=context, count=count,
context=context, count=False,
access_rights_uid=access_rights_uid)
if not ids:
if count:

View File

@ -132,20 +132,29 @@ class ir_ui_menu(osv.osv):
return len(result)
return result
def _get_full_name(self, cr, uid, ids, name, args, context):
res = {}
for m in self.browse(cr, uid, ids, context=context):
res[m.id] = self._get_one_full_name(m)
def name_get(self, cr, uid, ids, context=None):
res = []
for id in ids:
elmt = self.browse(cr, uid, id, context=context)
res.append((id, self._get_one_full_name(elmt)))
return res
def _get_one_full_name(self, menu, level=6):
def _get_full_name(self, cr, uid, ids, name=None, args=None, context=None):
if context == None:
context = {}
res = {}
for elmt in self.browse(cr, uid, ids, context=context):
res[elmt.id] = self._get_one_full_name(elmt)
return res
def _get_one_full_name(self, elmt, level=6):
if level<=0:
return '...'
if menu.parent_id:
parent_path = self._get_one_full_name(menu.parent_id, level-1) + "/"
if elmt.parent_id:
parent_path = self._get_one_full_name(elmt.parent_id, level-1) + "/"
else:
parent_path = ''
return parent_path + menu.name
return parent_path + elmt.name
def create(self, *args, **kwargs):
self.clear_cache()
@ -282,7 +291,7 @@ class ir_ui_menu(osv.osv):
'groups_id': fields.many2many('res.groups', 'ir_ui_menu_group_rel',
'menu_id', 'gid', 'Groups', help="If you have groups, the visibility of this menu will be based on these groups. "\
"If this field is empty, OpenERP will compute visibility based on the related object's read access."),
'complete_name': fields.function(_get_full_name,
'complete_name': fields.function(_get_full_name,
string='Full Path', type='char', size=128),
'icon': fields.selection(tools.icons, 'Icon', size=64),
'icon_pict': fields.function(_get_icon_pict, type='char', size=32),

View File

@ -120,7 +120,7 @@
<field name="name">ir.module.module.form</field>
<field name="model">ir.module.module</field>
<field name="arch" type="xml">
<form string="Module" version="7.0">
<form create="0" edit="0" string="Module" version="7.0">
<sheet>
<field name="icon_image" widget="image" class="oe_avatar oe_left"/>
<div class="oe_title">

View File

@ -361,6 +361,7 @@ class res_config_installer(osv.osv_memory):
'to install', ['uninstalled'], context=context)
cr.commit() #TOFIX: after remove this statement, installation wizard is fail
new_db, self.pool = pooler.restart_pool(cr.dbname, update_module=True)
res_config_installer()
DEPRECATION_MESSAGE = 'You are using an addon using old-style configuration '\
@ -546,6 +547,10 @@ class res_config_settings(osv.osv_memory):
'params': {'modules': to_install_names},
}
config = self.pool.get('res.config').next(cr, uid, [], context=context) or {}
if config.get('type') not in ('ir.actions.act_window_close',):
return config
# force client-side reload (update user menu and current view)
return {
'type': 'ir.actions.client',

View File

@ -47,7 +47,7 @@ class Country(osv.osv):
help='The full name of the country.', required=True, translate=True),
'code': fields.char('Country Code', size=2,
help='The ISO country code in two chars.\n'
'You can use this field for quick search.', required=True),
'You can use this field for quick search.'),
'address_format': fields.text('Address Format', help="""You can state here the usual format to use for the \
addresses belonging to this country.\n\nYou can use the python-style string patern with all the field of the address \
(for example, use '%(street)s' to display the field 'street') plus

View File

@ -31,8 +31,7 @@
<field name="code"/>
</group>
</group>
<label for="address_format" string="Address Format"/>
<field name="address_format" colspan="4" groups="base.group_no_one"/>
<field name="address_format" groups="base.group_no_one" placeholder="Address format..."/>
</form>
</field>
</record>

View File

@ -1,5 +1,7 @@
import test_ir_values, test_base
import test_base, test_expression, test_ir_values
checks = [
test_ir_values, test_base
test_base,
test_expression,
test_ir_values,
]

View File

@ -0,0 +1,72 @@
import unittest2
import openerp.tests.common as common
class test_expression(common.TransactionCase):
def test_in_not_in_m2m(self):
registry, cr, uid = self.registry, self.cr, self.uid
# Create 4 partners with no category, or one or two categories (out of two categories).
categories = registry('res.partner.category')
cat_a = categories.create(cr, uid, {'name': 'test_expression_category_A'})
cat_b = categories.create(cr, uid, {'name': 'test_expression_category_B'})
partners = registry('res.partner')
a = partners.create(cr, uid, {'name': 'test_expression_partner_A', 'category_id': [(6, 0, [cat_a])]})
b = partners.create(cr, uid, {'name': 'test_expression_partner_B', 'category_id': [(6, 0, [cat_b])]})
ab = partners.create(cr, uid, {'name': 'test_expression_partner_AB', 'category_id': [(6, 0, [cat_a, cat_b])]})
c = partners.create(cr, uid, {'name': 'test_expression_partner_C'})
# The tests.
# On a one2many or many2many field, `in` should be read `contains` (and
# `not in` should be read `doesn't contain`.
with_a = partners.search(cr, uid, [('category_id', 'in', [cat_a])])
self.assertEqual(set([a, ab]), set(with_a), "Search for category_id in cat_a failed.")
with_b = partners.search(cr, uid, [('category_id', 'in', [cat_b])])
self.assertEqual(set([ab, b]), set(with_b), "Search for category_id in cat_b failed.")
# Partners with the category A or the category B.
with_a_or_b = partners.search(cr, uid, [('category_id', 'in', [cat_a, cat_b])])
self.assertEqual(set([ab, a, b]), set(with_a_or_b), "Search for category_id contains cat_a or cat_b failed.")
# Show that `contains list` is really `contains element or contains element`.
with_a_or_with_b = partners.search(cr, uid, ['|', ('category_id', 'in', [cat_a]), ('category_id', 'in', [cat_b])])
self.assertEqual(set([ab, a, b]), set(with_a_or_with_b), "Search for category_id contains cat_a or contains cat_b failed.")
# If we change the OR in AND...
with_a_and_b = partners.search(cr, uid, [('category_id', 'in', [cat_a]), ('category_id', 'in', [cat_b])])
self.assertEqual(set([ab]), set(with_a_and_b), "Search for category_id contains cat_a and cat_b failed.")
# Partners without category A and without category B.
without_a_or_b = partners.search(cr, uid, [('category_id', 'not in', [cat_a, cat_b])])
self.assertTrue(all(i not in without_a_or_b for i in [a, b, ab]), "Search for category_id doesn't contain cat_a or cat_b failed (1).")
self.assertTrue(c in without_a_or_b, "Search for category_id doesn't contain cat_a or cat_b failed (2).")
# Show that `doesn't contain list` is really `doesn't contain element and doesn't contain element`.
without_a_and_without_b = partners.search(cr, uid, [('category_id', 'not in', [cat_a]), ('category_id', 'not in', [cat_b])])
self.assertTrue(all(i not in without_a_and_without_b for i in [a, b, ab]), "Search for category_id doesn't contain cat_a and cat_b failed (1).")
self.assertTrue(c in without_a_and_without_b, "Search for category_id doesn't contain cat_a and cat_b failed (2).")
# We can exclude any partner containing the category A.
without_a = partners.search(cr, uid, [('category_id', 'not in', [cat_a])])
self.assertTrue(a not in without_a, "Search for category_id doesn't contain cat_a failed (1).")
self.assertTrue(ab not in without_a, "Search for category_id doesn't contain cat_a failed (2).")
self.assertTrue(set([b, c]).issubset(set(without_a)), "Search for category_id doesn't contain cat_a failed (3).")
# (Obviously we can do the same for cateory B.)
without_b = partners.search(cr, uid, [('category_id', 'not in', [cat_b])])
self.assertTrue(b not in without_b, "Search for category_id doesn't contain cat_b failed (1).")
self.assertTrue(ab not in without_b, "Search for category_id doesn't contain cat_b failed (2).")
self.assertTrue(set([a, c]).issubset(set(without_b)), "Search for category_id doesn't contain cat_b failed (3).")
# We can't express the following: Partners with a category different than A.
# with_any_other_than_a = ...
# self.assertTrue(a not in with_any_other_than_a, "Search for category_id with any other than cat_a failed (1).")
# self.assertTrue(ab in with_any_other_than_a, "Search for category_id with any other than cat_a failed (2).")

View 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()

View File

@ -9,6 +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_view_validation, test_uninstall, test_misc, test_db_cursor
fast_suite = [
@ -20,6 +21,7 @@ checks = [
test_html_sanitize,
test_db_cursor,
test_orm,
test_per_class_teardown,
test_view_validation,
test_misc,
]

View File

@ -1,4 +1,8 @@
# -*- coding: utf-8 -*-
"""
The module :mod:`openerp.tests.common` provides a few helper and classes to write
tests.
"""
import os
import threading
import time
@ -40,10 +44,25 @@ def stop_openerp():
"""
openerp.service.stop_services()
class TransactionCase(unittest2.TestCase):
class BaseCase(unittest2.TestCase):
"""
Subclass of TestCase with a single transaction, rolled-back at the end of
the tests.
Subclass of TestCase for common OpenERP-specific code.
"""
@classmethod
def cursor(self):
return openerp.modules.registry.RegistryManager.get(DB).db.cursor()
@classmethod
def registry(self, model):
return openerp.modules.registry.RegistryManager.get(DB)[model]
class TransactionCase(BaseCase):
"""
Subclass of BaseCase with a single transaction, rolled-back at the end of
each test (method).
"""
def setUp(self):
@ -54,19 +73,31 @@ class TransactionCase(unittest2.TestCase):
self.cr.rollback()
self.cr.close()
def cursor(self):
return openerp.modules.registry.RegistryManager.get(DB).db.cursor()
def registry(self, model):
return openerp.modules.registry.RegistryManager.get(DB)[model]
class SingleTransactionCase(BaseCase):
"""
Subclass of BaseCase with a single transaction for the whole class,
rolled-back after all the tests.
"""
@classmethod
def setUpClass(cls):
cls.cr = cls.cursor()
cls.uid = openerp.SUPERUSER_ID
@classmethod
def tearDownClass(cls):
cls.cr.rollback()
cls.cr.close()
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

View File

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
import unittest2
import openerp
import common
class test_per_class_teardown(common.SingleTransactionCase):
"""
Check the whole-class transaction behavior of SingleTransactionCase.
"""
def test_00(self):
"""Create a partner."""
cr, uid = self.cr, self.uid
self.registry('res.partner').create(cr, uid, {'name': 'test_per_class_teardown_partner'})
ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
self.assertEqual(1, len(ids), "Test partner not found.")
def test_01(self):
"""Find the created partner."""
cr, uid = self.cr, self.uid
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):
"""
Check the per-method transaction behavior of TransactionCase.
"""
def test_00(self):
"""Create a partner."""
cr, uid = self.cr, self.uid
ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
self.assertEqual(0, len(ids), "Test partner found.")
self.registry('res.partner').create(cr, uid, {'name': 'test_per_class_teardown_partner'})
ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
self.assertEqual(1, len(ids), "Test partner not found.")
def test_01(self):
"""Don't find the created partner."""
cr, uid = self.cr, self.uid
ids = self.registry('res.partner').search(cr, uid, [('name', '=', 'test_per_class_teardown_partner')])
self.assertEqual(0, len(ids), "Test partner found.")
if __name__ == '__main__':
unittest2.main()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -597,7 +597,7 @@ def get_iso_codes(lang):
ALL_LANGUAGES = {
'ab_RU': u'Abkhazian / аҧсуа',
'ar_AR': u'Arabic / الْعَرَبيّة',
'ar_SY': u'Arabic / الْعَرَبيّة',
'bg_BG': u'Bulgarian / български език',
'bs_BS': u'Bosnian / bosanski jezik',
'ca_ES': u'Catalan / Català',

View File

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

View File

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