[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-b370b4fb-102a-4ea1-9d9b-02baffdfbe0c":3,"$fCQPS_IHlK5NzciUHakwyXiOvQ69DfcpVOlMEan1wSdo":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"b370b4fb-102a-4ea1-9d9b-02baffdfbe0c","odoo-automated-tests","使用TransactionCase、HttpCase和浏览器巡检测试运行Odoo自动化测试。涵盖测试数据设置、模拟和持续集成集成。","cat_coding_review","mod_coding","sickn33,coding","---\nname: odoo-automated-tests\ndescription: \"Write and run Odoo automated tests using TransactionCase, HttpCase, and browser tour tests. Covers test data setup, mocking, and CI integration.\"\nrisk: safe\nsource: \"self\"\n---\n\n# 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\u002Ftest_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.\u002Fodoo-bin --test-enable --stop-after-init -d my_database -u hospital_management\n\n# Run only tests tagged with a specific tag\n.\u002Fodoo-bin --test-enable --stop-after-init -d my_database \\\n  --test-tags hospital_management\n\n# Run a specific test class\n.\u002Fodoo-bin --test-enable --stop-after-init -d my_database \\\n  --test-tags \u002Fhospital_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('\u002Fhospital\u002Fpatients')\n        self.assertEqual(resp.status_code, 200)\n\n    def test_patient_page_redirects_unauthenticated(self):\n        # No authenticate() call = public\u002Fanonymous user\n        resp = self.url_open('\u002Fhospital\u002Fpatients', 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\u002Froute 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.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,137,1355,"2026-05-16 13:31:54",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"代码审查","review","mdi-magnify-scan","代码质量分析、安全审查",4,145,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"b9bada8b-d9c8-4ae5-95e4-22efe0ff452a","1.0.0","odoo-automated-tests.zip",2150,"uploads\u002Fskills\u002Fb370b4fb-102a-4ea1-9d9b-02baffdfbe0c\u002Fodoo-automated-tests.zip","69c16750a9b656b6d1d3c404bd2c188817a0d0dfc8418e562548ea25e3494ed2","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":5126}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]