While unit tests validate logic in isolation (either frontend or
backend), Tour Tests simulate real user behavior across both ends —
providing a complete picture of how the frontend and backend
interact in real-world flows.
Odoo 18 continues to support and improve Tour testing by using the
built-in QUnit test runner and web_tour module to simulate clicks,
inputs, and page navigations in the browser using a step-by-step
scenario.
A tour test acts like an automated walkthrough of your app — it
mimics a real user navigating your UI.
Tour Test File Structure
Here’s a recommended structure for adding a tour test to your module:
your_module/
├── static/
│ └── tests/
│ └── tours/
│ └── student_tour.js ← Tour steps
├── tests/
│ ├── __init__.py
│ └── test_student_tour.py ← Python test that starts the tour
├── __manifest__.py
Step 1: Register Your Tour
In student_tour.js, register your tour using web_tour.tour.register.
/** @odoo-module **/
import tour from 'web_tour.tour';
import { _t } from 'web.core';
import { Markup } from 'web.utils';
tour.register('student_tour', {
url: "/web",
test: true,
}, [
// Steps go here...
]);
- url: Where the tour should start.
- test: true: Marks this tour to be used only in test mode.
- wait_for: Optional condition to wait for before the tour begins.
- skip_enabled: Shows a "Skip" button (good for manual tours).
Step 2: Define Tour Steps
Tour steps simulate actions like clicking a button, typing in a
field, or selecting from a dropdown.
[
tour.stepUtils.showAppsMenuItem(),
{
trigger: '.o_app[data-menu-xmlid="student.menu_research_management_root"]',
content: Markup(_t('Want to manage your books? It starts here.')),
position: 'bottom',
},
{
trigger: '.o_list_button_add',
content: _t('Let\'s create your first book by clicking on create.'),
position: 'bottom',
},
{
trigger: '.o_field_widget[name="name"]',
content: _t('Fill in the book name.'),
run: function (actions) {
actions.text('War and Peace', this.$anchor.find('input'));
},
position: 'right',
}
]
- trigger: CSS selector for the element to act upon
- run: A function executed on the selected element (e.g., text
input)
- content: Tooltip text shown during the tour
- position: Tooltip position: "top", "right", "bottom", "left"
- auto: If false, waits for user action before proceeding
- in_modal: Limits search to modal window if set to true
- timeout: Max wait time (in ms) for this step
Step 3: Register the Tour in the Manifest
Make sure the tour script is included in the web.assets_backend
section of __manifest__.py:
'assets': {
'web.assets_backend': [
'student/static/tests/tours/student_tour.js',
],
},
Step 4: Create a Python Test to Launch the Tour
Create a test file in the tests/ directory to call your JS tour:
from odoo.tests.common import HttpCase, tagged
@tagged('post_install', '-at_install', 'student')
class TestUi(HttpCase):
def test_01_student_tour(self):
self.start_tour("/web", 'student_tour', login="admin")
@tagged ensures that the test runs only after module installation and
is excluded from auto-run if needed.
Step 5: Run the Tour Test
Run the server with the test command:
./odoo-bin -c odoo18.conf -i student --test-tags=student
This launches the test environment, executes the tour scenario using
the browser, and validates success.
The following log will be shown if our test case was successful.
...INFO test odoo.addons.student.tests.student_tour.TestBook:
console log: Tour student_tour succeeded