SuperAPI AI 工具集

odoo-automated-tests

测试与质量

查看项目

更新于 10-16 02:24

技能介绍

用途

Odoo 内置了基于 Python unittest 的测试框架。该技能帮助开发者编写 TransactionCase 单元测试、HttpCase 集成测试和 JavaScript tour 测试,并覆盖在 CI 流水线中运行测试的相关内容。

适用场景包括:

  • 为自定义模型的业务逻辑编写单元测试。
  • 创建 HTTP 测试以验证控制器端点。
  • 调试 CI 流水线中的测试失败。
  • 通过 --test-enable 配置自动化测试执行。

主要能力

该技能可生成完整的测试类代码,包含 setup、teardown 和断言,并提供执行测试所需的 odoo CLI 命令。

使用方式为:提及 @odoo-automated-tests 并描述要测试的功能,即可生成测试代码与运行命令。

使用方式与示例

TransactionCase 单元测试(Odoo 15+ 模式)

# tests/test_hospital_patient.py
from odoo.tests.common import TransactionCase
from odoo.tests import tagged
from odoo.exceptions import ValidationError

@tagged('post_install', '-at_install')
class TestHospitalPatient(TransactionCase):

    @classmethod
    def setUpClass(cls):
        # Use setUpClass for performance — runs once per class, not per test
        super().setUpClass()
        cls.Patient = cls.env['hospital.patient']
        cls.doctor = cls.env['res.users'].browse(cls.env.uid)

    def test_create_patient(self):
        patient = self.Patient.create({
            'name': 'John Doe',
            'doctor_id': self.doctor.id,
        })
        self.assertEqual(patient.state, 'draft')
        self.assertEqual(patient.name, 'John Doe')

    def test_confirm_patient(self):
        patient = self.Patient.create({'name': 'Jane Smith'})
        patient.action_confirm()
        self.assertEqual(patient.state, 'confirmed')

    def test_empty_name_raises_error(self):
        with self.assertRaises(ValidationError):
            self.Patient.create({'name': ''})

    def test_access_denied_for_other_user(self):
        # Test security rules by running as a different user
        other_user = self.env.ref('base.user_demo')
        with self.assertRaises(Exception):
            self.Patient.with_user(other_user).create({'name': 'Test'})

setUpClass 与 setUp 的对比:使用 setUpClass(Odoo 15+)共享测试数据。它每个类只运行一次,比每个测试方法都重新初始化的 setUp 快得多。

通过 CLI 运行测试

# Run all tests for a specific module
./odoo-bin --test-enable --stop-after-init -d my_database -u hospital_management

# Run only tests tagged with a specific tag
./odoo-bin --test-enable --stop-after-init -d my_database \
  --test-tags hospital_management

# Run a specific test class
./odoo-bin --test-enable --stop-after-init -d my_database \
  --test-tags /hospital_management:TestHospitalPatient

使用 HttpCase 测试控制器

from odoo.tests.common import HttpCase
from odoo.tests import tagged

@tagged('post_install', '-at_install')
class TestPatientController(HttpCase):

    def test_patient_page_authenticated(self):
        # Authenticate as a user, not with hardcoded password
        self.authenticate(self.env.user.login, self.env.user.login)
        resp = self.url_open('/hospital/patients')
        self.assertEqual(resp.status_code, 200)

    def test_patient_page_redirects_unauthenticated(self):
        # No authenticate() call = public/anonymous user
        resp = self.url_open('/hospital/patients', allow_redirects=False)
        self.assertIn(resp.status_code, [301, 302, 403])

最佳实践

  • 建议:使用 setUpClass() 配合 cls.env,而不是 setUp()——对大型测试套件而言速度显著更快。
  • 建议:使用 @tagged('post_install', '-at_install') 在所有模块安装后运行测试。
  • 建议:同时测试正常路径和错误条件(ValidationError、AccessError、UserError)。
  • 建议:使用 self.with_user(user) 测试访问控制,而不调用 sudo()。
  • 避免:使用生产数据库进行测试——始终使用专用测试数据库。
  • 避免:依赖测试执行顺序——每个 TransactionCase 测试都在隔离状态下回滚。
  • 避免:在 HttpCase.authenticate() 中硬编码密码——使用 self.env.user.login 或固定用户。

限制

  • JavaScript tour 测试需要运行中的浏览器(通过 phantomjs 或 Chrome headless)和实时 Odoo 服务器——此处未深入覆盖。
  • HttpCase 测试比 TransactionCase 慢得多——仅用于控制器/路由验证。
  • 不覆盖模拟外部服务(例如在测试中模拟 SMTP 服务器或支付网关)。
  • 测试隔离是在事务级别而非数据库级别——提交数据的测试(例如通过 cr.commit())可能在测试之间泄漏状态。