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

DBT单元测试遇结构体字段过多时执行失败的解决办法

DBT单元测试处理大结构体字段的问题与解决方案

问题描述

我在Databricks上运行DBT模型,实施单元测试时遇到了结构体字段过多导致的语法错误。

我的DBT单元测试代码如下:

unit_tests:
  - name: test_my_model
    model: my_model

    given:
      - input: source('my_schema', 'my_table_1')
        rows:
          - {application_id: 1, created_at: "2025-01-01"}
          - {application_id: 2, created_at: "2025-01-03"}

      - input: ref('reference__reference__days')
        rows:
          - {date: "2025-01-01"}
          - {date: "2025-01-02"}
          - {date: "2025-01-03"}

      - input: source('my_schema', 'my_table_2')
        rows:
          - {id: 10, application_id: 1, effective_on: "2025-01-01"}
          - {id: 11, application_id: 1, effective_on: "2025-01-02"}
          - {id: 20, application_id: 2, effective_on: "2025-01-03"}
          - {id: 21, application_id: 2, effective_on: "2025-01-03"}

    expect:
      rows:
        - {application_id: 1, date: "2025-01-01", effective_on: "2025-01-01"}
        - {application_id: 1, date: "2025-01-02", effective_on: "2025-01-02"}
        - {application_id: 1, date: "2025-01-03", effective_on: "2025-01-02"}
        - {application_id: 2, date: "2025-01-03", effective_on: "2025-01-03"}

运行测试时出现语法错误,错误信息显示DBT生成的SQL中结构体字段被截断(比如[20 more sub_fields...]),导致Databricks无法解析:

Runtime Error in unit_test test_my_model (tests/unit/test_path/test_my_model.yml)
  An error occurred during execution of unit test 'test_my_model'. There may be an error in the unit test definition: check the data types.
   Database Error
    
    [PARSE_SYNTAX_ERROR] Syntax error at or near '.'. SQLSTATE: 42601 
    
    == SQL ==
    /* {"app": "dbt", "dbt_version": "1.9.4", "dbt_databricks_version": "1.10.2", "databricks_sql_connector_version": "4.0.3"} */
    
        
      
        create or replace temporary view `test_my_model__dbt_tmp` as
          select * from (
            
    
    
    with
         __dbt__cte__table_1 as (
    
    -- Fixture for table_1
    select 
      cast(null as bigint) as field_1, 
      cast(null as timestamp) as field_2, 
      cast(null as array<struct<sub_field_1:boolean,sub_field_2:boolean,[20 more sub_fields...],... 108 more fields>>) as field_3,
    --------------------------------------------------------------------------------------------^^^
     [more fields...]

我需要解决两个问题:

  • 强制DBT发送完整Schema而非截断内容;
  • 仅发送结构体中的必要字段而非全部字段。

解决方案

1. 强制DBT发送完整Schema,避免截断

DBT默认会对过长的Schema定义进行截断,可通过修改项目配置禁用或调整截断长度:

在dbt_project.yml中添加或修改以下配置:

tests:
  unit:
    schema_truncation_length: 0  # 0表示不截断,也可设置足够大的数值(如100000)

该配置控制单元测试生成SQL时Schema字段的截断长度,设置为0即可强制发送完整的结构体定义。

注意:若使用旧版本dbt-databricks插件,建议升级到1.11.0+版本,该版本优化了结构体字段的处理逻辑。

2. 仅发送结构体中的必要字段

如果模型只用到结构体中的部分子字段,可通过以下两种方式减少测试中的字段数量:

方式一:在单元测试fixture中明确指定所需字段

在given部分的输入定义里,用columns参数指定模型需要的字段(包括结构体的子字段),替代自动生成的全量Schema:

given:
  - input: source('my_schema', 'my_table_1')
    columns:
      - name: application_id
        data_type: bigint
      - name: created_at
        data_type: timestamp
      - name: field_3
        data_type: array<struct<sub_field_1:boolean, sub_field_2:boolean>>  # 仅包含需要的子字段
    rows:
      - {application_id: 1, created_at: "2025-01-01", field_3: []}
      - {application_id: 2, created_at: "2025-01-03", field_3: []}

这种方式直接定义测试所需的字段和类型,避免生成不必要的结构体子字段。

方式二:创建测试专用的简化视图

在dbt项目中创建仅包含模型所需字段的视图,代替原表作为测试依赖:

-- models/test_utils/my_table_1_simplified.sql
select
  application_id,
  created_at,
  array_transform(field_3, x -> struct(x.sub_field_1, x.sub_field_2)) as field_3
from {{ source('my_schema', 'my_table_1') }}

然后在单元测试中引用这个视图:

given:
  - input: ref('my_table_1_simplified')
    rows:
      - {application_id: 1, created_at: "2025-01-01", field_3: []}
      - {application_id: 2, created_at: "2025-01-03", field_3: []}

这种方式适合多个测试场景需要复用简化结构的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 01:52:01