You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GitHub推送时自动运行Odoo单元测试及API执行问题排查

问题1:Odoo.sh推送代码时自动运行特定模块测试的配置方法

要实现Odoo.sh推送代码时自动运行指定模块的测试,可通过以下方式配置:

1. 配置.odoo-ci.yml文件

在仓库根目录创建该文件,明确指定要运行的测试模块,示例配置如下:

test:
  modules:
    # 直接指定目标模块
    - your_custom_sale_module
    # 或指定模块+测试标签,仅运行带对应标签的测试用例
    - name: your_custom_sale_module
      tags: ['sale_uat', 'post_install']

Odoo.sh在代码推送时会读取该配置,自动执行指定模块的测试任务。

2. 为测试方法添加标签

在测试类的方法上添加@tagged装饰器,标记测试类型,配合CI配置精准触发:

from odoo.tests import tagged, TransactionCase

@tagged('sale_uat', 'post_install')
class TestSaleProject(TransactionCase):
    def test_sale_order_with_project_task(self):
        # 测试逻辑代码
        pass

注:post_install标签表示测试需在模块安装后运行,适合依赖已安装模块数据的场景。

3. 开启分支自动测试

确保目标分支在Odoo.sh后台开启了"自动测试"选项,推送代码后系统会自动执行配置的测试任务。


问题2:API调用测试第二次卡住的修复方案

你直接实例化测试类并手动调用setUpClass的方式,不符合Odoo测试框架的生命周期管理逻辑,会导致测试环境残留(如未回滚的数据库事务、已创建的测试记录),第二次调用时出现卡住问题。修复方案如下:

正确的测试执行方式:使用unittest测试运行器

通过Python标准库的unittest.TestLoader和TestRunner加载并运行测试,Odoo测试框架会自动处理事务回滚、环境清理等流程。修改后的控制器代码示例:

import unittest
import json
from odoo import fields, _
from odoo.http import Controller, Response, route
from odoo.logger import logging
from your_module.tests.test_sale_project import TestSaleProject

_logger = logging.getLogger(__name__)
_webhook_sale = '/webhook/execute_sale_uat'

class TestExecutionController(Controller):
    @route(_webhook_sale, auth='none', type='http', methods=['POST'], csrf=False)
    def execute_sale_order_uat(self, **post):
        _logger.info("begin execute_sale_order_uat")
        try:
            self.authenticate_token_and_environment(scope='sale_access')
            _logger.info("Authenticated successfully")
            
            # 加载测试类为测试套件
            loader = unittest.TestLoader()
            test_suite = loader.loadTestsFromTestCase(TestSaleProject)
            
            # 运行测试(将输出重定向到/dev/null避免日志冗余,可按需调整)
            runner = unittest.TextTestRunner(stream=open('/dev/null', 'w'), verbosity=2)
            test_result = runner.run(test_suite)
            
            # 根据测试结果返回响应
            if test_result.wasSuccessful():
                response_data = {
                    'code'   : 200,
                    'result' : 'success',
                    'message': _(f"Sale UATs executed successfully on {fields.Datetime.now()}"),
                }
                return Response(json.dumps(response_data), status=200, content_type='application/json')
            else:
                # 收集失败/错误信息
                error_details = []
                for test_case, err in test_result.failures + test_result.errors:
                    error_details.append(f"{test_case.id()}: {err}")
                response_data = {
                    'code'   : 500,
                    'result' : 'failed',
                    'message': _("部分测试执行失败"),
                    'errors' : error_details
                }
                return Response(json.dumps(response_data), status=500, content_type='application/json')
            
        except Exception as e:
            _logger.error(f"执行UAT测试出错: {str(e)}", exc_info=True)
            response_data = {
                'code'   : 500,
                'result' : 'error',
                'message': _(f"测试执行异常: {str(e)}")
            }
            return Response(json.dumps(response_data), status=500, content_type='application/json')

关键注意事项

  1. 测试类必须继承自odoo.tests.common.TransactionCase(或其子类),确保每个测试方法在独立事务中运行,执行后自动回滚,避免数据残留。
  2. 不要手动调用setUpClass、tearDownClass等方法,测试运行器会自动按生命周期执行这些方法。
  3. 若需在测试中使用特定环境(如特定公司、用户),可在测试类的setUp方法中初始化,而非控制器中处理。

内容的提问来源于stack exchange,提问作者Victor Macario

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:53:12