{"id":"30b4011b-ea6d-4d64-9bc2-2cc079513c17","shortId":"V7j3PM","kind":"skill","title":"odoo-automated-tests","tagline":"Write and run Odoo automated tests using TransactionCase, HttpCase, and browser tour tests. Covers test data setup, mocking, and CI integration.","description":"# Odoo Automated Tests\n\n## Overview\n\nOdoo has a built-in testing framework based on Python's `unittest`. This skill helps you write `TransactionCase` unit tests, `HttpCase` integration tests, and JavaScript tour tests. It also covers running tests in CI pipelines.\n\n## When to Use This Skill\n\n- Writing unit tests for a custom model's business logic.\n- Creating an HTTP test to verify a controller endpoint.\n- Debugging test failures in a CI pipeline.\n- Setting up automated test execution with `--test-enable`.\n\n## How It Works\n\n1. **Activate**: Mention `@odoo-automated-tests` and describe the feature to test.\n2. **Generate**: Get complete test class code with setup, teardown, and assertions.\n3. **Run**: Get the exact `odoo` CLI command to execute your tests.\n\n## Examples\n\n### Example 1: TransactionCase Unit Test (Odoo 15+ pattern)\n\n```python\n# tests/test_hospital_patient.py\nfrom odoo.tests.common import TransactionCase\nfrom odoo.tests import tagged\nfrom odoo.exceptions import ValidationError\n\n@tagged('post_install', '-at_install')\nclass TestHospitalPatient(TransactionCase):\n\n    @classmethod\n    def setUpClass(cls):\n        # Use setUpClass for performance — runs once per class, not per test\n        super().setUpClass()\n        cls.Patient = cls.env['hospital.patient']\n        cls.doctor = cls.env['res.users'].browse(cls.env.uid)\n\n    def test_create_patient(self):\n        patient = self.Patient.create({\n            'name': 'John Doe',\n            'doctor_id': self.doctor.id,\n        })\n        self.assertEqual(patient.state, 'draft')\n        self.assertEqual(patient.name, 'John Doe')\n\n    def test_confirm_patient(self):\n        patient = self.Patient.create({'name': 'Jane Smith'})\n        patient.action_confirm()\n        self.assertEqual(patient.state, 'confirmed')\n\n    def test_empty_name_raises_error(self):\n        with self.assertRaises(ValidationError):\n            self.Patient.create({'name': ''})\n\n    def test_access_denied_for_other_user(self):\n        # Test security rules by running as a different user\n        other_user = self.env.ref('base.user_demo')\n        with self.assertRaises(Exception):\n            self.Patient.with_user(other_user).create({'name': 'Test'})\n```\n\n> **`setUpClass` vs `setUp`:** Use `setUpClass` (Odoo 15+) for shared test data. It runs once per class and is significantly faster than `setUp` which re-initializes for every single test method.\n\n### Example 2: Run Tests via CLI\n\n```bash\n# Run all tests for a specific module\n./odoo-bin --test-enable --stop-after-init -d my_database -u hospital_management\n\n# Run only tests tagged with a specific tag\n./odoo-bin --test-enable --stop-after-init -d my_database \\\n  --test-tags hospital_management\n\n# Run a specific test class\n./odoo-bin --test-enable --stop-after-init -d my_database \\\n  --test-tags /hospital_management:TestHospitalPatient\n```\n\n### Example 3: HttpCase for Controller Testing\n\n```python\nfrom odoo.tests.common import HttpCase\nfrom odoo.tests import tagged\n\n@tagged('post_install', '-at_install')\nclass TestPatientController(HttpCase):\n\n    def test_patient_page_authenticated(self):\n        # Authenticate as a user, not with hardcoded password\n        self.authenticate(self.env.user.login, self.env.user.login)\n        resp = self.url_open('/hospital/patients')\n        self.assertEqual(resp.status_code, 200)\n\n    def test_patient_page_redirects_unauthenticated(self):\n        # No authenticate() call = public/anonymous user\n        resp = self.url_open('/hospital/patients', allow_redirects=False)\n        self.assertIn(resp.status_code, [301, 302, 403])\n```\n\n## Best Practices\n\n- ✅ **Do:** Use `setUpClass()` with `cls.env` instead of `setUp()` — it is dramatically faster for large test suites.\n- ✅ **Do:** Use `@tagged('post_install', '-at_install')` to run tests after all modules are installed.\n- ✅ **Do:** Test both the happy path and error conditions (`ValidationError`, `AccessError`, `UserError`).\n- ✅ **Do:** Use `self.with_user(user)` to test access control without calling `sudo()`.\n- ❌ **Don't:** Use a production database for tests — always use a dedicated test database.\n- ❌ **Don't:** Rely on test execution order — each `TransactionCase` test is rolled back in isolation.\n- ❌ **Don't:** Hardcode passwords in `HttpCase.authenticate()` — use `self.env.user.login` or a fixture user.\n\n## Limitations\n\n- **JavaScript tour tests** require a running browser (via `phantomjs` or `Chrome headless`) and a live Odoo server — not covered in depth here.\n- `HttpCase` tests are significantly slower than `TransactionCase` — use them only for controller/route verification.\n- Does not cover **mocking external services** (e.g., mocking an SMTP server or payment gateway in tests).\n- Test isolation is at the **transaction level**, not database level — tests that commit data (e.g., via `cr.commit()`) can leak state between tests.","tags":["odoo","automated","tests","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding"],"capabilities":["skill","source-sickn33","skill-odoo-automated-tests","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/odoo-automated-tests","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34666 github stars · SKILL.md body (4,873 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-23T06:51:40.343Z","embedding":null,"createdAt":"2026-04-18T21:41:40.570Z","updatedAt":"2026-04-23T06:51:40.343Z","lastSeenAt":"2026-04-23T06:51:40.343Z","tsv":"'/hospital/patients':428,448 '/hospital_management':383 '/odoo-bin':326,348,369 '1':109,148 '15':153,287 '2':122,313 '200':432 '3':134,386 '301':455 '302':456 '403':457 'access':251,510 'accesserror':501 'activ':110 'allow':449 'also':59 'alway':523 'assert':133 'authent':412,414,441 'autom':3,9,27,99,114 'back':541 'base':38 'base.user':269 'bash':318 'best':458 'brows':200 'browser':15,563 'built':34 'built-in':33 'busi':79 'call':442,513 'chrome':567 'ci':24,64,95 'class':127,174,188,296,368,405 'classmethod':177 'cli':140,317 'cls':180 'cls.doctor':197 'cls.env':195,198,464 'cls.env.uid':201 'cls.patient':194 'code':128,431,454 'command':141 'commit':620 'complet':125 'condit':499 'confirm':224,233,236 'control':88,389,511 'controller/route':590 'cover':18,60,575,594 'cr.commit':624 'creat':81,204,278 'custom':76 'd':334,356,377 'data':20,291,621 'databas':336,358,379,520,528,616 'debug':90 'dedic':526 'def':178,202,222,237,249,408,433 'demo':270 'deni':252 'depth':577 'describ':117 'differ':264 'doctor':212 'doe':211,221 'draft':217 'dramat':470 'e.g':598,622 'empti':239 'enabl':105,329,351,372 'endpoint':89 'error':242,498 'everi':308 'exact':138 'exampl':146,147,312,385 'except':273 'execut':101,143,534 'extern':596 'failur':92 'fals':451 'faster':300,471 'featur':119 'fixtur':554 'framework':37 'gateway':605 'generat':123 'get':124,136 'happi':495 'hardcod':420,546 'headless':568 'help':45 'hospit':338,362 'hospital.patient':196 'http':83 'httpcase':13,51,387,395,407,579 'httpcase.authenticate':549 'id':213 'import':159,163,167,394,398 'init':333,355,376 'initi':306 'instal':171,173,402,404,480,482,490 'instead':465 'integr':25,52 'isol':543,609 'jane':230 'javascript':55,557 'john':210,220 'larg':473 'leak':626 'level':614,617 'limit':556 'live':571 'logic':80 'manag':339,363 'mention':111 'method':311 'mock':22,595,599 'model':77 'modul':325,488 'name':209,229,240,248,279 'odoo':2,8,26,30,113,139,152,286,572 'odoo-automated-test':1,112 'odoo.exceptions':166 'odoo.tests':162,397 'odoo.tests.common':158,393 'open':427,447 'order':535 'overview':29 'page':411,436 'password':421,547 'path':496 'patient':205,207,225,227,410,435 'patient.action':232 'patient.name':219 'patient.state':216,235 'pattern':154 'payment':604 'per':187,190,295 'perform':184 'phantomj':565 'pipelin':65,96 'post':170,401,479 'practic':459 'product':519 'public/anonymous':443 'python':40,155,391 'rais':241 're':305 're-initi':304 'redirect':437,450 'reli':531 'requir':560 'res.users':199 'resp':425,445 'resp.status':430,453 'roll':540 'rule':259 'run':7,61,135,185,261,293,314,319,340,364,484,562 'secur':258 'self':206,226,243,256,413,439 'self.assertequal':215,218,234,429 'self.assertin':452 'self.assertraises':245,272 'self.authenticate':422 'self.doctor.id':214 'self.env.ref':268 'self.env.user.login':423,424,551 'self.patient.create':208,228,247 'self.patient.with':274 'self.url':426,446 'self.with':505 'server':573,602 'servic':597 'set':97 'setup':21,130,283,302,467 'setupclass':179,182,193,281,285,462 'share':289 'signific':299,582 'singl':309 'skill':44,70 'skill-odoo-automated-tests' 'slower':583 'smith':231 'smtp':601 'source-sickn33' 'specif':324,346,366 'state':627 'stop':331,353,374 'stop-after-init':330,352,373 'sudo':514 'suit':475 'super':192 'tag':164,169,343,347,361,382,399,400,478 'teardown':131 'test':4,10,17,19,28,36,50,53,57,62,73,84,91,100,104,115,121,126,145,151,191,203,223,238,250,257,280,290,310,315,321,328,342,350,360,367,371,381,390,409,434,474,485,492,509,522,527,533,538,559,580,607,608,618,629 'test-en':103,327,349,370 'test-tag':359,380 'testhospitalpati':175,384 'testpatientcontrol':406 'tests/test_hospital_patient.py':156 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'tour':16,56,558 'transact':613 'transactioncas':12,48,149,160,176,537,585 'u':337 'unauthent':438 'unit':49,72,150 'unittest':42 'use':11,68,181,284,461,477,504,517,524,550,586 'user':255,265,267,275,277,417,444,506,507,555 'usererror':502 'validationerror':168,246,500 'verif':591 'verifi':86 'via':316,564,623 'vs':282 'without':512 'work':108 'write':5,47,71","prices":[{"id":"7225325c-4062-457a-beb6-f8f52a1fd35e","listingId":"30b4011b-ea6d-4d64-9bc2-2cc079513c17","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:41:40.570Z"}],"sources":[{"listingId":"30b4011b-ea6d-4d64-9bc2-2cc079513c17","source":"github","sourceId":"sickn33/antigravity-awesome-skills/odoo-automated-tests","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/odoo-automated-tests","isPrimary":false,"firstSeenAt":"2026-04-18T21:41:40.570Z","lastSeenAt":"2026-04-23T06:51:40.343Z"}],"details":{"listingId":"30b4011b-ea6d-4d64-9bc2-2cc079513c17","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"odoo-automated-tests","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34666,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-23T06:41:03Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"62caaf8599c35a045dea43762d625c675051add0","skill_md_path":"skills/odoo-automated-tests/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/odoo-automated-tests"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"odoo-automated-tests","description":"Write and run Odoo automated tests using TransactionCase, HttpCase, and browser tour tests. Covers test data setup, mocking, and CI integration."},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/odoo-automated-tests"},"updatedAt":"2026-04-23T06:51:40.343Z"}}