[IMP] crm: split results-oriented from perf-oriented assign tests
Purpose is to split assign tests related to results (leads being assigned, with deduplication, compared to team and member domains) from tests related to performance (query counters). Assign process is a random process: randomizing teams leads to searching, assigning and de-duplicating leads in various order. As a lot of search are implied during assign process query counters may vary from run to run. "Heavy" performance test included here ranged from 6K to 6.3K queries. Either we set high counters maximum which makes those tests less useful. Either we avoid random if possible which is what we decided to do by setting the seed of random in tests. SPECIFICATIONS For results oriented tests remove query counters. Those tests should simply ensure results of assign process, notably that even with random choice between team and users we always have leads assigned with right domain and counts. For performance oriented tests using query counters set random seed to have a reproducible scenario and have less random in query counters. LINKS Task ID-2446759 (lead merge priority field management) Task ID-2446883 (query counters fix) PR odoo/odoo#65016
This commit is contained in:
@@ -10,3 +10,4 @@ from . import test_crm_lead_merge
|
||||
from . import test_crm_activity
|
||||
from . import test_crm_ui
|
||||
from . import test_crm_pls
|
||||
from . import test_performances
|
||||
|
||||
@@ -421,7 +421,8 @@ class TestLeadConvertCommon(TestCrmCommon):
|
||||
if member.crm_team_id.assignment_domain:
|
||||
self.assertEqual(
|
||||
member_leads.filtered_domain(literal_eval(member.crm_team_id.assignment_domain)),
|
||||
member_leads
|
||||
member_leads,
|
||||
'Assign domain not matching: %s' % member.crm_team_id.assignment_domain
|
||||
)
|
||||
|
||||
class TestLeadConvertMassCommon(TestLeadConvertCommon):
|
||||
|
||||
@@ -8,15 +8,15 @@ from unittest.mock import patch
|
||||
from odoo import fields
|
||||
from odoo.addons.crm.tests.common import TestLeadConvertCommon
|
||||
from odoo.tests.common import tagged
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('lead_assign')
|
||||
class TestLeadAssign(TestLeadConvertCommon):
|
||||
""" Test lead assignment feature added in saas-13.5. """
|
||||
class TestLeadAssignCommon(TestLeadConvertCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestLeadAssign, cls).setUpClass()
|
||||
super(TestLeadAssignCommon, cls).setUpClass()
|
||||
cls._switch_to_multi_membership()
|
||||
cls._switch_to_auto_assign()
|
||||
|
||||
@@ -52,6 +52,11 @@ class TestLeadAssign(TestLeadConvertCommon):
|
||||
self.assertEqual(self.sales_team_convert_m1.lead_month_count, 0)
|
||||
self.assertEqual(self.sales_team_convert_m2.lead_month_count, 0)
|
||||
|
||||
|
||||
@tagged('lead_assign')
|
||||
class TestLeadAssign(TestLeadAssignCommon):
|
||||
""" Test lead assignment feature added in saas-14.2 """
|
||||
|
||||
def test_assign_configuration(self):
|
||||
now_patch = datetime(2020, 11, 2, 10, 0, 0)
|
||||
|
||||
@@ -98,7 +103,10 @@ class TestLeadAssign(TestLeadConvertCommon):
|
||||
self.assertFalse(self.assign_cron.active)
|
||||
self.assertEqual(self.assign_cron.nextcall, datetime(2020, 11, 1, 10, 0, 0))
|
||||
|
||||
def test_crm_team_assign_duplicates(self):
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_assign_duplicates(self):
|
||||
""" Test assign process with duplicates on partner. Allow to ensure notably
|
||||
that de duplication is effectively performed. """
|
||||
leads = self._create_leads_batch(
|
||||
lead_type='lead',
|
||||
user_ids=[False],
|
||||
@@ -115,8 +123,7 @@ class TestLeadAssign(TestLeadConvertCommon):
|
||||
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
|
||||
|
||||
with self.with_user('user_sales_manager'):
|
||||
with self.assertQueryCount(user_sales_manager=467): # crm only: 460
|
||||
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
|
||||
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
|
||||
|
||||
# teams assign
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
@@ -148,7 +155,8 @@ class TestLeadAssign(TestLeadConvertCommon):
|
||||
])
|
||||
self.assertEqual(len(new_assigned_leads_wpartner), 2)
|
||||
|
||||
def test_crm_team_assign_no_duplicates(self):
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_assign_no_duplicates(self):
|
||||
leads = self._create_leads_batch(
|
||||
lead_type='lead',
|
||||
user_ids=[False],
|
||||
@@ -165,8 +173,7 @@ class TestLeadAssign(TestLeadConvertCommon):
|
||||
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
|
||||
|
||||
with self.with_user('user_sales_manager'):
|
||||
with self.assertQueryCount(user_sales_manager=206): # crm only: 201
|
||||
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
|
||||
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
|
||||
|
||||
# teams assign
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
@@ -183,10 +190,11 @@ class TestLeadAssign(TestLeadConvertCommon):
|
||||
self.assertMemberAssign(self.sales_team_convert_m1, 2) # 30 max on 15
|
||||
self.assertMemberAssign(self.sales_team_convert_m2, 4) # 60 max on 15
|
||||
|
||||
def test_crm_team_assign_populated(self):
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_assign_populated(self):
|
||||
""" Test assignment on a more high volume oriented test set in order to
|
||||
have more insights on query counts. """
|
||||
# create leads enough to have interesting counters
|
||||
test more real life use cases. """
|
||||
# create leads enough to assign one month of work
|
||||
_lead_count, _email_dup_count, _partner_count = 500, 50, 150
|
||||
leads = self._create_leads_batch(
|
||||
lead_type='lead',
|
||||
@@ -240,8 +248,7 @@ class TestLeadAssign(TestLeadConvertCommon):
|
||||
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
|
||||
|
||||
with self.with_user('user_sales_manager'):
|
||||
with self.assertQueryCount(user_sales_manager=6289): # crm only: 6165
|
||||
self.env['crm.team'].browse(sales_teams.ids)._action_assign_leads(work_days=30)
|
||||
self.env['crm.team'].browse(sales_teams.ids)._action_assign_leads(work_days=30)
|
||||
|
||||
self.members.invalidate_cache(fnames=['lead_month_count'])
|
||||
self.assertMemberAssign(self.sales_team_1_m1, 45) # 45 max on one month
|
||||
|
||||
@@ -24,7 +24,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
|
||||
with self.assertQueryCount(user_sales_manager=0):
|
||||
test_leads = self.env['crm.lead'].browse(test_leads.ids)
|
||||
|
||||
with self.assertQueryCount(user_sales_manager=254): # crm only: 252
|
||||
with self.assertQueryCount(user_sales_manager=255): # crm only: 252
|
||||
test_leads._handle_salesmen_assignment(user_ids=user_ids, team_id=False)
|
||||
|
||||
self.assertEqual(test_leads.team_id, self.sales_team_convert | self.sales_team_1)
|
||||
@@ -42,7 +42,7 @@ class TestLeadConvertMass(crm_common.TestLeadConvertMassCommon):
|
||||
with self.assertQueryCount(user_sales_manager=0):
|
||||
test_leads = self.env['crm.lead'].browse(test_leads.ids)
|
||||
|
||||
with self.assertQueryCount(user_sales_manager=220): # crm only: 218
|
||||
with self.assertQueryCount(user_sales_manager=223): # crm only: 218
|
||||
test_leads._handle_salesmen_assignment(user_ids=user_ids, team_id=team_id)
|
||||
|
||||
self.assertEqual(test_leads.team_id, self.sales_team_convert)
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import random
|
||||
|
||||
from odoo.addons.crm.tests.test_crm_lead_assignment import TestLeadAssignCommon
|
||||
from odoo.tests.common import tagged
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('lead_assign')
|
||||
class TestLeadAssignPerf(TestLeadAssignCommon):
|
||||
""" Test performances of lead assignment feature added in saas-14.2
|
||||
|
||||
Assign process is a random process: randomizing teams leads to searching,
|
||||
assigning and de-duplicating leads in various order. As a lot of search
|
||||
are implied during assign process query counters may vary from run to run.
|
||||
"Heavy" performance test included here ranged from 6K to 6.3K queries. Either
|
||||
we set high counters maximum which makes those tests less useful. Either we
|
||||
avoid random if possible which is what we decided to do by setting the seed
|
||||
of random in tests.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestLeadAssignPerf, cls).setUpClass()
|
||||
random.seed(2042)
|
||||
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.crm.models.crm_team', 'odoo.addons.crm.models.crm_team_member')
|
||||
def test_assign_perf_duplicates(self):
|
||||
""" Test assign process with duplicates on partner. Allow to ensure notably
|
||||
that de duplication is effectively performed. """
|
||||
leads = self._create_leads_batch(
|
||||
lead_type='lead',
|
||||
user_ids=[False],
|
||||
partner_ids=[self.contact_1.id, self.contact_2.id, False, False, False],
|
||||
count=50
|
||||
)
|
||||
self.assertInitialData()
|
||||
|
||||
# assign probability to leads (bypass auto probability as purpose is not to test pls)
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
for idx in range(0, 5):
|
||||
sliced_leads = leads[idx:len(leads):5]
|
||||
for lead in sliced_leads:
|
||||
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
|
||||
|
||||
with self.with_user('user_sales_manager'):
|
||||
with self.assertQueryCount(user_sales_manager=470): # crm only: 465
|
||||
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
|
||||
|
||||
# teams assign
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
leads_st1 = leads.filtered_domain([('team_id', '=', self.sales_team_1.id)])
|
||||
leads_stc = leads.filtered_domain([('team_id', '=', self.sales_team_convert.id)])
|
||||
self.assertEqual(len(leads_st1), 10) # 2 * 2 * 75 / 30.0
|
||||
self.assertEqual(len(leads_stc), 12) # 2 * 2 * 90 / 30.0
|
||||
|
||||
# salespersons assign
|
||||
self.members.invalidate_cache(fnames=['lead_month_count'])
|
||||
self.assertMemberAssign(self.sales_team_1_m1, 3) # 45 max on 2 days
|
||||
self.assertMemberAssign(self.sales_team_1_m2, 1) # 15 max on 2 days
|
||||
self.assertMemberAssign(self.sales_team_1_m3, 1) # 15 max on 2 days
|
||||
self.assertMemberAssign(self.sales_team_convert_m1, 2) # 30 max on 15
|
||||
self.assertMemberAssign(self.sales_team_convert_m2, 4) # 60 max on 15
|
||||
|
||||
# run a second round to finish leads
|
||||
with self.with_user('user_sales_manager'):
|
||||
with self.assertQueryCount(user_sales_manager=131): # crm only: 123
|
||||
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
|
||||
|
||||
# teams assign: everything should be done due to duplicates
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
self.assertTrue(len(leads.filtered_domain([('team_id', '=', False)])) == 0)
|
||||
|
||||
# deduplicate should have removed all duplicated linked to contact_1 and contact_2
|
||||
new_assigned_leads_wpartner = self.env['crm.lead'].search([
|
||||
('partner_id', 'in', (self.contact_1 | self.contact_2).ids),
|
||||
('id', 'in', leads.ids)
|
||||
])
|
||||
self.assertEqual(len(new_assigned_leads_wpartner), 2)
|
||||
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.crm.models.crm_team', 'odoo.addons.crm.models.crm_team_member')
|
||||
def test_assign_perf_no_duplicates(self):
|
||||
leads = self._create_leads_batch(
|
||||
lead_type='lead',
|
||||
user_ids=[False],
|
||||
partner_ids=[False],
|
||||
count=50
|
||||
)
|
||||
self.assertInitialData()
|
||||
|
||||
# assign probability to leads (bypass auto probability as purpose is not to test pls)
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
for idx in range(0, 5):
|
||||
sliced_leads = leads[idx:len(leads):5]
|
||||
for lead in sliced_leads:
|
||||
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
|
||||
|
||||
with self.with_user('user_sales_manager'):
|
||||
with self.assertQueryCount(user_sales_manager=210): # crm only: 206
|
||||
self.env['crm.team'].browse(self.sales_teams.ids)._action_assign_leads(work_days=2)
|
||||
|
||||
# teams assign
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
leads_st1 = leads.filtered_domain([('team_id', '=', self.sales_team_1.id)])
|
||||
leads_stc = leads.filtered_domain([('team_id', '=', self.sales_team_convert.id)])
|
||||
self.assertEqual(len(leads_st1), 10) # 2 * 2 * 75 / 30.0
|
||||
self.assertEqual(len(leads_stc), 12) # 2 * 2 * 90 / 30.0
|
||||
|
||||
# salespersons assign
|
||||
self.members.invalidate_cache(fnames=['lead_month_count'])
|
||||
self.assertMemberAssign(self.sales_team_1_m1, 3) # 45 max on 2 days
|
||||
self.assertMemberAssign(self.sales_team_1_m2, 1) # 15 max on 2 days
|
||||
self.assertMemberAssign(self.sales_team_1_m3, 1) # 15 max on 2 days
|
||||
self.assertMemberAssign(self.sales_team_convert_m1, 2) # 30 max on 15
|
||||
self.assertMemberAssign(self.sales_team_convert_m2, 4) # 60 max on 15
|
||||
|
||||
@mute_logger('odoo.models.unlink', 'odoo.addons.crm.models.crm_team', 'odoo.addons.crm.models.crm_team_member')
|
||||
def test_assign_perf_populated(self):
|
||||
""" Test assignment on a more high volume oriented test set in order to
|
||||
have more insights on query counts. """
|
||||
# create leads enough to have interesting counters
|
||||
_lead_count, _email_dup_count, _partner_count = 500, 50, 150
|
||||
leads = self._create_leads_batch(
|
||||
lead_type='lead',
|
||||
user_ids=[False],
|
||||
partner_count=_partner_count,
|
||||
country_ids=[self.env.ref('base.be').id, self.env.ref('base.fr').id, False],
|
||||
count=_lead_count,
|
||||
email_dup_count=_email_dup_count)
|
||||
self.assertInitialData()
|
||||
# assign for one month, aka a lot
|
||||
self.env.ref('crm.ir_cron_crm_lead_assign').write({'interval_type': 'days', 'interval_number': 30})
|
||||
self.env['ir.config_parameter'].set_param('crm.assignment.bundle', '20')
|
||||
# create a third team
|
||||
sales_team_3 = self.env['crm.team'].create({
|
||||
'name': 'Sales Team 3',
|
||||
'sequence': 15,
|
||||
'alias_name': False,
|
||||
'use_leads': True,
|
||||
'use_opportunities': True,
|
||||
'company_id': False,
|
||||
'user_id': False,
|
||||
'assignment_domain': [('country_id', '!=', False)],
|
||||
})
|
||||
sales_team_3_m1 = self.env['crm.team.member'].create({
|
||||
'user_id': self.user_sales_manager.id,
|
||||
'crm_team_id': sales_team_3.id,
|
||||
'assignment_max': 60,
|
||||
'assignment_domain': False,
|
||||
})
|
||||
sales_team_3_m2 = self.env['crm.team.member'].create({
|
||||
'user_id': self.user_sales_leads.id,
|
||||
'crm_team_id': sales_team_3.id,
|
||||
'assignment_max': 60,
|
||||
'assignment_domain': False,
|
||||
})
|
||||
sales_team_3_m3 = self.env['crm.team.member'].create({
|
||||
'user_id': self.user_sales_salesman.id,
|
||||
'crm_team_id': sales_team_3.id,
|
||||
'assignment_max': 15,
|
||||
'assignment_domain': [('probability', '>=', 10)],
|
||||
})
|
||||
sales_teams = self.sales_teams | sales_team_3
|
||||
self.assertEqual(sum(team.assignment_max for team in sales_teams), 300)
|
||||
self.assertEqual(len(leads), 550)
|
||||
|
||||
# assign probability to leads (bypass auto probability as purpose is not to test pls)
|
||||
leads = self.env['crm.lead'].search([('id', 'in', leads.ids)]) # ensure order
|
||||
for idx in range(0, 5):
|
||||
sliced_leads = leads[idx:len(leads):5]
|
||||
for lead in sliced_leads:
|
||||
lead.probability = (idx + 1) * 10 * ((int(lead.priority) + 1) / 2)
|
||||
|
||||
with self.with_user('user_sales_manager'):
|
||||
with self.assertQueryCount(user_sales_manager=6246): # crm only: 6237
|
||||
self.env['crm.team'].browse(sales_teams.ids)._action_assign_leads(work_days=30)
|
||||
|
||||
self.members.invalidate_cache(fnames=['lead_month_count'])
|
||||
self.assertMemberAssign(self.sales_team_1_m1, 45) # 45 max on one month
|
||||
self.assertMemberAssign(self.sales_team_1_m2, 15) # 15 max on one month
|
||||
self.assertMemberAssign(self.sales_team_1_m3, 15) # 15 max on one month
|
||||
self.assertMemberAssign(self.sales_team_convert_m1, 30) # 30 max on one month
|
||||
self.assertMemberAssign(self.sales_team_convert_m2, 60) # 60 max on one month
|
||||
self.assertMemberAssign(sales_team_3_m1, 60) # 60 max on one month
|
||||
self.assertMemberAssign(sales_team_3_m2, 60) # 60 max on one month
|
||||
self.assertMemberAssign(sales_team_3_m3, 15) # 15 max on one month
|
||||
Reference in New Issue
Block a user