155 lines
7.0 KiB
Python
155 lines
7.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import collections
|
|
import logging
|
|
from odoo.tests import common
|
|
from odoo.cli.populate import Populate
|
|
from odoo.tools import mute_logger, populate
|
|
from unittest.mock import patch
|
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
# todo patch cursor commit
|
|
class TestPopulate(common.TransactionCase):
|
|
def setUp(self):
|
|
super(TestPopulate, self).setUp()
|
|
patcher = patch.object(self.cr, 'commit')
|
|
self.startPatcher(patcher)
|
|
|
|
def test_dependency(self):
|
|
ordered_models = Populate._get_ordered_models(self.env, ['test.populate'])
|
|
ordered_models_names = [model._name for model in ordered_models]
|
|
self.assertEqual(ordered_models_names, ['test.populate.category', 'test.populate'])
|
|
|
|
@mute_logger('odoo.cli.populate')
|
|
def test_no_populate(self):
|
|
""" Check that model with no populate method are not populated"""
|
|
model = 'test.no.populate'
|
|
populated = Populate.populate(self.env, 'small', [model])
|
|
new = populated[model]
|
|
self.assertFalse(new)
|
|
|
|
@mute_logger('odoo.cli.populate')
|
|
def test_populate(self):
|
|
""" Check that model with populate methods are correctly populated"""
|
|
model = 'test.populate'
|
|
populated = Populate.populate(self.env, 'small', [model])
|
|
records = self.check_test_populate_values(populated, model)
|
|
|
|
# pseudo random after cartesian with ~ 1/4 False, 3/4 True
|
|
# seed is model dependant
|
|
self.assertEqual(records.mapped('active')[6:20], [
|
|
True, True, True, True, True, True, False, False, True, True, True, True, False, True
|
|
])
|
|
# pseudo random after iterate
|
|
self.assertEqual(records.mapped('some_ref')[5:20], [
|
|
1, 0, 2, 4, 4, 3, 4, 1, 2, 2, 2, 4, 4, 1, 2
|
|
])
|
|
self.assertEqual(records.mapped('sequence')[:20], [6, 10, 1, 1, 1, 3, 8, 9, 1, 5, 9, 5, 7, 3, 5, 3, 6, 4, 9, 2]) # Test randint
|
|
|
|
@mute_logger('odoo.cli.populate')
|
|
def test_populate_inherit(self):
|
|
""" Check that model with populate methods are correctly populated"""
|
|
model = 'test.populate.inherit'
|
|
populated = Populate.populate(self.env, 'small', [model])
|
|
records = self.check_test_populate_values(populated, model) # should be same values as base class
|
|
# and additionnal_field has own values set
|
|
# iterate then pseudo random
|
|
self.assertEqual(records.mapped('additionnal_field')[:20], [
|
|
'V1', 'V2', 'V3', # iterate
|
|
'V3', 'V1', 'V2', 'V1', 'V2', 'V1', 'V2', 'V2', 'V2', 'V1', 'V1', 'V3', 'V1', 'V2', 'V2', 'V3', 'V2' # pseudorandom
|
|
])
|
|
|
|
def check_test_populate_values(self, populated, model):
|
|
new = populated[model]
|
|
self.assertTrue(new)
|
|
records = self.env[model].browse(new)
|
|
# main cartesian product
|
|
self.assertEqual(records.mapped('active')[:6], [
|
|
True, True, True,
|
|
False, False, False,
|
|
])
|
|
self.assertEqual(records.mapped('state')[:6], [
|
|
False, 'a', 'b',
|
|
False, 'a', 'b',
|
|
])
|
|
|
|
# custom name call
|
|
self.assertEqual(records.mapped('name')[:6], [
|
|
'active_corner_0', 'active_corner_1', 'active_corner_2',
|
|
'inactive_corner_3', 'inactive_corner_4', 'inactive_corner_5',
|
|
])
|
|
self.assertIn('filling', records.mapped('name')[6]) # filling when cartesian and iterate are done
|
|
# iterate then pseudo random
|
|
self.assertEqual(records.mapped('some_ref')[:5], [
|
|
0, 1, 2, 3, 4 # iterate
|
|
])
|
|
|
|
# some custom multi field generator (as cartesian product in this example)
|
|
self.assertEqual(records.mapped('dependant_field_1')[:6], [
|
|
'd1_1', 'd1_1', 'd1_1',
|
|
'd1_2', 'd1_2', 'd1_2'
|
|
])
|
|
self.assertEqual(records.mapped('dependant_field_2')[:6], [
|
|
'd2_1', 'd2_2', 'd2_3_0',
|
|
'd2_1', 'd2_2', 'd2_3_1'
|
|
])
|
|
used_category_ids = set(records.mapped('category_id').ids[:20])
|
|
self.assertEqual(len(used_category_ids), 6) # event if id may change, with given seed, the 6 category are used
|
|
generated_category_ids = set(populated['test.populate.category'])
|
|
self.assertFalse(used_category_ids-generated_category_ids) # all category are the generated one
|
|
self.assertFalse(hasattr(self.env.registry, 'populated_models'), 'populated_models flag has been removed from registry')
|
|
|
|
return records
|
|
|
|
|
|
@common.tagged('-at_install', 'post_install')
|
|
class TestPopulateValidation(common.TransactionCase):
|
|
""" check that all fields in _populate_factories exists """
|
|
def setUp(self):
|
|
super(TestPopulateValidation, self).setUp()
|
|
self.env.registry.populated_models = collections.defaultdict(list)
|
|
self.addCleanup(delattr, self.env.registry, 'populated_models')
|
|
|
|
def test_populate_factories(self):
|
|
for model in self.env.values():
|
|
factories = model._populate_factories() or []
|
|
factories_fields = set([field_name for field_name, factory in factories if not field_name.startswith('_')])
|
|
missing = factories_fields - model._fields.keys()
|
|
self.assertFalse(missing, 'Fields %s not found in model %s' % (missing, model._name))
|
|
|
|
|
|
@common.tagged('-standard', '-at_install', 'post_install', 'missing_populate')
|
|
class TestPopulateMissing(common.TransactionCase):
|
|
""" check that all fields in _populate_factories exists """
|
|
def setUp(self):
|
|
super(TestPopulateMissing, self).setUp()
|
|
self.env.registry.populated_models = collections.defaultdict(list)
|
|
self.addCleanup(delattr, self.env.registry, 'populated_models')
|
|
|
|
def test_populate_missing_factories(self):
|
|
no_factory_models = []
|
|
for model in self.env.values():
|
|
factories = model._populate_factories()
|
|
if not factories:
|
|
if model._transient or model._abstract:
|
|
continue
|
|
ir_model = self.env['ir.model'].search([('model', '=', model._name)])
|
|
if all(module.startswith('test_') for module in ir_model.modules.split(',')):
|
|
continue
|
|
no_factory_models.append(model._name)
|
|
else:
|
|
factories_fields = next(populate.chain_factories(factories, model._name)).keys()
|
|
def is_electable(field):
|
|
return not field.compute \
|
|
and field.store \
|
|
and field.name not in ('create_uid', 'write_uid', 'write_date', 'create_date', 'id') \
|
|
and field.type not in ('many2many', 'one2many')
|
|
electable_fields = set([key for key, field in model._fields.items() if is_electable(field)])
|
|
no_factory_fields = set(electable_fields - factories_fields)
|
|
if no_factory_fields:
|
|
_logger.info('Model %s has some undefined field: %s', model._name, no_factory_fields)
|
|
|
|
_logger.info('No populate factories defiend for %s', no_factory_models)
|