[IMP] test_event_full: add performance on frontend and registration tour
Purpose of this commit is to add performance tests for some commonly used URLs related to event: the main event page and browsing a given event. A complete registration tour involving buying tickets, answering questions and filling billing information is also added under a query counter check. This allows to see a bit how many queries are involved in that flow. To ease reproduction a data is added but not imported, allowing to quickly see what happens locally instead of having to debug tests. Task-2703285 (Event performance improvements) Task-2703289 (Event testing and coverage) Part-of: odoo/odoo#81068
This commit is contained in:
@@ -17,6 +17,7 @@ automatic lead generation, full Online support, ...
|
||||
'event_crm_sale',
|
||||
'event_sale',
|
||||
'event_sms',
|
||||
'payment_test',
|
||||
'website_event_booth_sale_exhibitor',
|
||||
'website_event_crm_questions',
|
||||
'website_event_exhibitor',
|
||||
@@ -28,6 +29,7 @@ automatic lead generation, full Online support, ...
|
||||
'website_event_track_quiz',
|
||||
],
|
||||
'data': [
|
||||
# 'data/event_type_data.xml', # uncomment to reproduce test tour
|
||||
'data/ir_actions_report_data.xml',
|
||||
'views/event_registration_templates_reports.xml',
|
||||
],
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data noupdate="0">
|
||||
|
||||
<record id="event_booth_category_data_1" model="event.booth.category">
|
||||
<field name="description" type="html"><p>Standard</p></field>
|
||||
<field name="name">Standard</field>
|
||||
<field name="product_id" ref="event_booth_sale.product_product_event_booth"/>
|
||||
</record>
|
||||
<record id="event_booth_category_data_2" model="event.booth.category">
|
||||
<field name="description" type="html"><p>Premium</p></field>
|
||||
<field name="name">Premium</field>
|
||||
<field name="product_id" ref="event_booth_sale.product_product_event_booth"/>
|
||||
<field name="price">90</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_data_full" model="event.type">
|
||||
<field name="auto_confirm" eval="True"/>
|
||||
<field name="default_timezone">Europe/Paris</field>
|
||||
<field name="event_type_booth_ids" eval="[
|
||||
(5, 0),
|
||||
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_1'),
|
||||
'name': 'Standard Booth',
|
||||
}
|
||||
),
|
||||
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_1'),
|
||||
'name': 'Standard Booth 2',
|
||||
}
|
||||
),
|
||||
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_2'),
|
||||
'name': 'Premium Booth',
|
||||
}
|
||||
),
|
||||
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_2'),
|
||||
'name': 'Premium Booth 2',
|
||||
}
|
||||
)]"/>
|
||||
<field name="event_type_mail_ids" eval="[
|
||||
(5, 0),
|
||||
(0, 0, {'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
'notification_type': 'mail',
|
||||
'template_ref': 'mail.template,%i' % ref('event.event_subscription'),
|
||||
}
|
||||
),
|
||||
(0, 0, {'interval_nbr': 1,
|
||||
'interval_unit': 'days',
|
||||
'interval_type': 'before_event',
|
||||
'notification_type': 'mail',
|
||||
'template_ref': 'mail.template,%i' % ref('event.event_reminder'),
|
||||
}
|
||||
),
|
||||
(0, 0, {'interval_nbr': 1,
|
||||
'interval_unit': 'days',
|
||||
'interval_type': 'after_event',
|
||||
'notification_type': 'sms',
|
||||
'template_ref': 'sms.template,%i' % ref('event_sms.sms_template_data_event_reminder'),
|
||||
}
|
||||
)]"/>
|
||||
<field name="event_type_ticket_ids" eval="[
|
||||
(5, 0),
|
||||
(0, 0, {'description': 'Ticket1 Description',
|
||||
'name': 'Ticket1',
|
||||
'product_id': ref('event_sale.product_product_event'),
|
||||
'seats_max': 10,
|
||||
}
|
||||
),
|
||||
(0, 0, {'description': 'Ticket2 Description',
|
||||
'name': 'Ticket2',
|
||||
'product_id': ref('event_sale.product_product_event'),
|
||||
'price': 45,
|
||||
}
|
||||
)]"/>
|
||||
<field name="has_seats_limitation" eval="True"/>
|
||||
<field name="name">Test Type</field>
|
||||
<field name="note" type="html"><p>Template note</p></field>
|
||||
<field name="question_ids" eval="[(5, 0)]"/>
|
||||
<field name="seats_max">30</field>
|
||||
<field name="tag_ids" eval="[(5, 0)]"/>
|
||||
<field name="ticket_instructions" type="html"><p>Ticket Instructions</p></field>
|
||||
<field name="website_menu" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="event_question_type_full_1" model="event.question">
|
||||
<field name="question_type">simple_choice</field>
|
||||
<field name="once_per_order" eval="False"/>
|
||||
<field name="event_type_id" ref="test_event_full.event_type_data_full"/>
|
||||
<field name="title">Question1</field>
|
||||
</record>
|
||||
<record id="event_question_type_full_1_answer_1" model="event.question.answer">
|
||||
<field name="name">Q1-Answer1</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="question_id" ref="test_event_full.event_question_type_full_1"/>
|
||||
</record>
|
||||
<record id="event_question_type_full_1_answer_2" model="event.question.answer">
|
||||
<field name="name">Q1-Answer2</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="question_id" ref="test_event_full.event_question_type_full_1"/>
|
||||
</record>
|
||||
<record id="event_question_type_full_2" model="event.question">
|
||||
<field name="question_type">simple_choice</field>
|
||||
<field name="once_per_order" eval="False"/>
|
||||
<field name="event_type_id" ref="test_event_full.event_type_data_full"/>
|
||||
<field name="title">Question2</field>
|
||||
</record>
|
||||
<record id="event_question_type_full_2_answer_1" model="event.question.answer">
|
||||
<field name="name">Q2-Answer1</field>
|
||||
<field name="sequence">1</field>
|
||||
<field name="question_id" ref="test_event_full.event_question_type_full_2"/>
|
||||
</record>
|
||||
<record id="event_question_type_full_2_answer_2" model="event.question.answer">
|
||||
<field name="name">Q2-Answer2</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="question_id" ref="test_event_full.event_question_type_full_2"/>
|
||||
</record>
|
||||
<record id="event_question_type_full_3" model="event.question">
|
||||
<field name="question_type">text_box</field>
|
||||
<field name="once_per_order" eval="True"/>
|
||||
<field name="event_type_id" ref="test_event_full.event_type_data_full"/>
|
||||
<field name="title">Question3</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -0,0 +1,85 @@
|
||||
odoo.define('test_event_full.tour.performance', function (require) {
|
||||
"use strict";
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
|
||||
var registerSteps = [{
|
||||
content: "Select 2 units of 'Ticket1' ticket type",
|
||||
trigger: '#o_wevent_tickets_collapse .row.o_wevent_ticket_selector[name="Ticket1"] select',
|
||||
run: 'text 2',
|
||||
}, {
|
||||
content: "Select 1 unit of 'Ticket2' ticket type",
|
||||
trigger: '#o_wevent_tickets_collapse .row.o_wevent_ticket_selector[name="Ticket2"] select',
|
||||
run: 'text 1',
|
||||
}, {
|
||||
content: "Click on 'Register' button",
|
||||
trigger: '#o_wevent_tickets .btn-primary:contains("Register"):not(:disabled)',
|
||||
run: 'click',
|
||||
}, {
|
||||
content: "Fill attendees details",
|
||||
trigger: 'form[id="attendee_registration"] .btn:contains("Continue")',
|
||||
run: function () {
|
||||
$("input[name='1-name']").val("Raoulette Poiluchette");
|
||||
$("input[name='1-phone']").val("0456112233");
|
||||
$("input[name='1-email']").val("raoulette@example.com");
|
||||
$("div[name*='Question1'] select[name*='question_answer-1']").val($("select[name*='question_answer-1'] option:contains('Q1-Answer2')").val());
|
||||
$("div[name*='Question2'] select[name*='question_answer-1']").val($("select[name*='question_answer-1'] option:contains('Q2-Answer1')").val());
|
||||
$("input[name='2-name']").val("Michel Tractopelle");
|
||||
$("input[name='2-phone']").val("0456332211");
|
||||
$("input[name='2-email']").val("michel@example.com");
|
||||
$("div[name*='Question1'] select[name*='question_answer-2']").val($("select[name*='question_answer-2'] option:contains('Q1-Answer1')").val());
|
||||
$("div[name*='Question2'] select[name*='question_answer-2']").val($("select[name*='question_answer-2'] option:contains('Q2-Answer2')").val());
|
||||
$("input[name='3-name']").val("Hubert Boitaclous");
|
||||
$("input[name='3-phone']").val("0456995511");
|
||||
$("input[name='3-email']").val("hubert@example.com");
|
||||
$("div[name*='Question1'] select[name*='question_answer-3']").val($("select[name*='question_answer-3'] option:contains('Q1-Answer2')").val());
|
||||
$("div[name*='Question2'] select[name*='question_answer-3']").val($("select[name*='question_answer-3'] option:contains('Q2-Answer2')").val());
|
||||
$("textarea[name*='question_answer']").text("Random answer from random guy");
|
||||
},
|
||||
}, {
|
||||
content: "Validate attendees details",
|
||||
extra_trigger: "input[name='1-name'], input[name='2-name'], input[name='3-name']",
|
||||
trigger: 'button:contains("Continue")',
|
||||
run: 'click',
|
||||
}, {
|
||||
content: "Address filling",
|
||||
trigger: 'select[name="country_id"]',
|
||||
run: function () {
|
||||
$('input[name="name"]').val('Raoulette Poiluchette');
|
||||
$('input[name="phone"]').val('0456112233');
|
||||
$('input[name="email"]').val('raoulette@example.com');
|
||||
$('input[name="street"]').val('Cheesy Crust Street, 42');
|
||||
$('input[name="city"]').val('CheeseCity');
|
||||
$('input[name="zip"]').val('8888');
|
||||
$('#country_id option:eq(1)').attr('selected', true);
|
||||
},
|
||||
}, {
|
||||
content: "Next",
|
||||
trigger: '.oe_cart .btn:contains("Next")',
|
||||
}, {
|
||||
content: 'Select Test payment acquirer',
|
||||
trigger: '.o_payment_option_card:contains("Test")'
|
||||
}, {
|
||||
content: 'Add card number',
|
||||
trigger: 'input[name="customer_input"]',
|
||||
run: 'text 4242424242424242'
|
||||
}, {
|
||||
content: "Pay now",
|
||||
extra_trigger: "#cart_products:contains(Ticket1):contains(Ticket2)",
|
||||
trigger: 'button:contains(Pay Now)',
|
||||
run: 'click',
|
||||
}, {
|
||||
content: 'Payment is successful',
|
||||
trigger: '.oe_website_sale_tx_status:contains("Your payment has been successfully processed.")',
|
||||
run: function () {}
|
||||
}];
|
||||
|
||||
|
||||
tour.register('wevent_performance_register', {
|
||||
test: true
|
||||
}, [].concat(
|
||||
registerSteps,
|
||||
)
|
||||
);
|
||||
|
||||
});
|
||||
@@ -5,6 +5,7 @@ from datetime import timedelta
|
||||
from freezegun import freeze_time
|
||||
|
||||
from odoo.addons.test_event_full.tests.common import TestEventFullCommon
|
||||
from odoo.addons.website.tests.test_performance import UtilPerf
|
||||
from odoo.tests.common import users, warmup, Form
|
||||
from odoo.tests import tagged
|
||||
|
||||
@@ -332,3 +333,90 @@ class TestRegistrationPerformance(EventPerformanceCase):
|
||||
self.website_customer_data[0],
|
||||
event_id=event.id)
|
||||
self.env['event.registration'].create([registration_values])
|
||||
|
||||
|
||||
@tagged('event_performance', 'event_online', 'post_install', '-at_install')
|
||||
class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestOnlineEventPerformance, cls).setUpClass()
|
||||
# if website_livechat is installed, disable it
|
||||
if 'channel_id' in cls.env['website']:
|
||||
cls.env['website'].search([]).channel_id = False
|
||||
|
||||
cash_journal = cls.env['account.journal'].create({
|
||||
'name': 'Cash - Test',
|
||||
'type': 'cash',
|
||||
'code': 'CASH - Test'
|
||||
})
|
||||
cls.env['payment.acquirer'].search([('provider', '=', 'test')]).write({
|
||||
'journal_id': cash_journal.id,
|
||||
'state': 'test'
|
||||
})
|
||||
|
||||
# clean even page to make it reproducible
|
||||
cls.env['event.event'].search([('name', '!=', 'Test Event')]).write({'active': False})
|
||||
# create noise for events
|
||||
cls.noise_events = cls.env['event.event'].create([
|
||||
{'name': 'Event %02d' % idx,
|
||||
'date_begin': cls.reference_now + timedelta(days=(-2 + int(idx/10))),
|
||||
'date_end': cls.reference_now + timedelta(days=5),
|
||||
'is_published': True,
|
||||
}
|
||||
for idx in range(0, 50)
|
||||
])
|
||||
|
||||
def _test_url_open(self, url):
|
||||
url += ('?' not in url and '?' or '') + '&nocache'
|
||||
return self.url_open(url)
|
||||
|
||||
@warmup
|
||||
def test_event_page_event_manager(self):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate('user_eventmanager', 'user_eventmanager')
|
||||
with self.assertQueryCount(default=65): # tef only: 64 (+1 ent)
|
||||
self._test_url_open('/event/%i' % self.test_event.id)
|
||||
|
||||
@warmup
|
||||
def test_event_page_public(self):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate(None, None)
|
||||
with self.assertQueryCount(default=43): # tef only: 43
|
||||
self._test_url_open('/event/%i' % self.test_event.id)
|
||||
|
||||
@warmup
|
||||
def test_events_browse_event_manager(self):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate('user_eventmanager', 'user_eventmanager')
|
||||
with self.assertQueryCount(default=51): # tef only: 50 (+1 ent)
|
||||
self._test_url_open('/event')
|
||||
|
||||
@warmup
|
||||
def test_events_browse_public(self):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate(None, None)
|
||||
with self.assertQueryCount(default=32): # tef only: 32
|
||||
self._test_url_open('/event')
|
||||
|
||||
# @warmup
|
||||
# def test_register_public(self):
|
||||
# with freeze_time(self.reference_now + timedelta(hours=3)): # be sure sales has started
|
||||
# self.assertTrue(self.test_event.event_registrations_started)
|
||||
# self.authenticate(None, None)
|
||||
# with self.assertQueryCount(default=99999): # tef only: 1110
|
||||
# self.browser_js(
|
||||
# '/event/%i/register' % self.test_event.id,
|
||||
# 'odoo.__DEBUG__.services["web_tour.tour"].run("wevent_performance_register")',
|
||||
# 'odoo.__DEBUG__.services["web_tour.tour"].tours.wevent_performance_register.ready',
|
||||
# login=None,
|
||||
# timeout=200,
|
||||
# )
|
||||
|
||||
# # minimal checkup, to be improved in future tests independently from performance
|
||||
# self.assertEqual(len(self.test_event.registration_ids), 3)
|
||||
# self.assertEqual(len(self.test_event.registration_ids.visitor_id), 1)
|
||||
|
||||
@@ -7,7 +7,7 @@ from odoo import tests
|
||||
from odoo.addons.test_event_full.tests.common import TestWEventCommon
|
||||
|
||||
|
||||
@tests.common.tagged('post_install', '-at_install')
|
||||
@tests.common.tagged('event_online', 'post_install', '-at_install')
|
||||
class TestWEventRegister(TestWEventCommon):
|
||||
|
||||
def test_register(self):
|
||||
|
||||
Reference in New Issue
Block a user