merge upstream
bzr revid: chs@openerp.com-20121031132638-nc2o9v0gnonl5l7l
This commit is contained in:
commit
478319c3ed
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
]
|
||||
|
|
|
@ -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).")
|
||||
|
|
@ -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,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,
|
||||
]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
|
@ -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à',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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