Odoo18-Base/odoo/addons/test_populate/tests/test_populate.py
2025-03-10 11:12:23 +07:00

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)