Use this skill to add practical tests for Odoo custom modules. Prefer tests at the Odoo behavior seam: ORM flows, constraints, computes, access rules, controllers, reports, forms, workflows, and integration boundaries.
First Move
Before writing tests:
- Identify the addon/module and target Odoo version.
- Inspect
__manifest__.py,models/,views/,security/,controllers/,report/,static/src/, existingtests/, and relevant docs. - If
$ODOO_SOURCEis set, inspect local test helpers and framework behavior instead of guessing.
Choose The Test Type
- Use
TransactionCasefor most model/business-logic tests. Each test runs in a savepoint and rolls back. - Use
AccountTestInvoicingCommonfor accounting tests needing companies, products, partners, taxes, journals, or invoices. - Use
Formhelper when testing default values, onchanges, form validations, One2many/Many2many form behavior, or user-like form flows. - Use
HttpCasefor browser, tour, website, portal, controller, or full UI flows. - Use
SingleTransactionCaseonly for read-only suites or expensive setup where cross-test state is acceptable. - Use
unittest.mock.patch/MagicMockfor external APIs, payment gateways, OAuth, webhooks, file system, time, or slow services. Do not mock Odoo internals unless there is no better seam.
Required Structure
your_module/
├── __init__.py # Do not import tests here
├── __manifest__.py
├── tests/
│ ├── __init__.py # Import test modules here
│ ├── common.py # Optional shared fixtures/helpers
│ └── test_*.py # Test files
Every new test_*.py must be imported from tests/__init__.py, or the Odoo test runner will not discover it.
Writing Workflow
- Map the behavior to prove and the smallest Odoo seam that proves it.
- Add or update
tests/common.pyonly for reusable fixtures/helpers. - Create fresh mutable records inside each test unless immutable setup belongs in
setUpClass. - Use Arrange, Act, Assert sections in test method body.
- Test happy path, validation/error path, and relevant side effects.
- For access/security changes, test realistic users/groups/companies with
with_user(). - For external integrations, patch the boundary where it is used, then assert both state changes and mock calls.
- For performance-sensitive code, add
assertQueryCountwhen supported by the target version/test base. - Update
tests/__init__.pyand manifest dependencies only when evidence requires it. - For OWL components, services, registries, and field widgets, compose with
odoo-web-testingand itsOWL-TESTING.mdreference.
Tags
Default pattern for post-install module tests:
from odoo.tests import tagged
@tagged("post_install", "-at_install")
class TestYourFeature(YourModuleTestCommon):
pass
References
- See ODOO-TESTING-SOP.md for the SOP, terminology, tags, and troubleshooting.
- See ODOO-TESTING-EXAMPLES.md for ready-to-adapt test patterns.
- Compose with
odoo-code-tracerwhen you need to trace the behavior before writing tests. - Compose with
odoo-code-reviewwhen reviewing test coverage or test quality.