mcpField
G
generate-cds-unit-test

generate-cds-unit-test

github.com/arc-mcp测试与质量239248 次安装2 天前更新
代码仓库

关于 generate-cds-unit-test

此技能根据 CDS 实体生成使用 CDS Test Double Framework 的 ABAP Unit 测试类,面向需要验证 CDS 逻辑的 ABAP 开发者。它分析实体语义并生成测试代码,支持预览、写入和验证流程。

主要功能

  1. 01读取 CDS 定义、字段及依赖
  2. 02识别可测试的 CDS 语义
  3. 03生成 ABAP Unit 测试类
  4. 04支持代码检查、激活与测试

适用场景

  1. 01为包含计算或筛选的 CDS 实体编写单元测试
  2. 02为 CDS 重构建立回归测试
  3. 03检查关联、聚合和 CASE 逻辑

MCP 相关

技能通过 ARC-1 访问 SAP,并使用 mcp-sap-docs 查询 CDS Test Double Framework 和 ABAP Unit 文档。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/arc-mcp/arc-1 --skill generate-cds-unit-test

安装后在 Claude Code 中输入/generate-cds-unit-test确认已加载。

详细介绍

生成 CDS 单元测试

使用 CDS 测试替身框架,为 CDS 实体生成 ABAP Unit 测试类。

此技能通过结合 ARC-1(SAP 系统访问)和 mcp-sap-docs(文档和最佳实践),复现 SAP Joule 的“CDS 单元测试生成”功能。

智能默认值(静默应用,不要询问)

设置默认值原因
测试类名称ZCL_TEST_<entity_name>标准约定
包$TMP快速原型开发
测试范围所有可测试语义用户查看列表后可缩小范围
风险级别HARMLESSCDS 测试替身不会修改真实数据
持续时间SHORT单元测试应快速运行

输入

用户提供 CDS 实体名称(例如,ZI_SALESORDER、ZC_TRAVEL)。

只需提供 CDS 实体名称。如果用户只提供实体名称,请应用智能默认值并立即继续。

用户也可以选择指定:

  • 测试类名称(默认值:ZCL_TEST_<entity_name>)
  • 包(默认值:$TMP)
  • 传输请求(仅非 $TMP 包需要)

第 1 步:收集 CDS 实体上下文

只需调用 3 次工具,即可读取 CDS 实体、其字段结构和所有依赖项。

1a. 读取 CDS DDL 源代码
SAPRead(type="DDLS", name="<entity_name>")
1b. 获取结构化字段列表
SAPRead(type="DDLS", name="<entity_name>", include="elements")

返回包含所有字段的格式化列表,其中包括键标记、别名、关联引用和表达式类型(计算、case、cast、coalesce)。使用此列表了解实体结构,无需解析原始 DDL。

1c. 获取依赖项上下文(表、视图、关联)
SAPContext(type="DDLS", name="<entity_name>")

自动从 CDS DDL 中提取所有数据源(FROM、JOIN)、关联、组合和投影基础。对于每个依赖项,都会通过类型回退(DDLS → TABL → STRU)获取完整源代码。由此可以了解:

  • 底层表定义及字段类型(用于创建类型正确的测试数据)
  • 其他 CDS 视图源(用于理解传递逻辑)
  • 关联目标

对于更深层的依赖关系图(例如,消费视图 → 接口视图 → 表),请使用 depth=2:

SAPContext(type="DDLS", name="<entity_name>", depth=2)
1d. (可选)读取元数据扩展和行为定义
SAPRead(type="DDLX", name="<entity_name>")
SAPRead(type="BDEF", name="<entity_name>")

如果不存在 DDLX/BDEF,这些操作可能会失败——无需担心,跳过即可。只有实体具有 UI 注解或 RAP 行为时才需要读取。

第 2 步:分析 CDS 语义并提出测试用例

首选方式(SAP_BASIS 8.16+ — ABAP Platform 2025 / S/4HANA 2025):直接询问 SAP。 SAP 会分析实体并返回权威的可测试语义列表——这与 SAP Joule 的 CDS 单元测试生成所用的 CDS 测试替身框架引擎相同:

SAPDiagnose(action="cds_testcases", name="<entity_name>")

每条建议都包含可直接使用的 testMethod 名称、semanticType(NONE = 整个视图、CALCULATION、CAST、JOIN、CASE 等)、description,以及计算或强制转换场景中的 calculatedField。将此列表作为下文“输出给用户”部分的建议测试用例列表:这是 SAP 自身的分析结果,因此优先于手动解析 DDL。将每个 semanticType 映射到类别表,并将每个 testMethod 映射到第 4 步中的 FOR TESTING 方法。如果工具返回“requires SAP_BASIS 8.16+”消息(较旧版本 / NW 7.5x 不提供此端点),或者你想交叉检查覆盖范围,请使用下方的手动分析方式。

备用方式 / 交叉检查 — 自行分析 DDL。 分析你在第 1 步读取的 CDS DDL 源代码,并找出所有可测试语义。按类别分组:

要查找的语义类别
类别在 DDL 中查找的内容测试用例示例
计算算术表达式(field1 * field2、field1 - field2)插入已知值,验证计算结果
CASE 表达式case when ... then ... else ... end每个分支各设计一个测试
类型转换cast(field as abap.dec(15,2))、cast(field as abap.char(10))插入值,验证转换结果
WHERE 筛选where status = 'A' 或 where amount > 0插入符合条件和不符合条件的行,验证仅显示符合条件的行
HAVING 子句having sum(amount) > 1000插入会触发和不会触发筛选条件的数据
JOINinner join、left outer join、association在两个表中插入键匹配的数据;对于外连接,使用不匹配的键进行测试
聚合使用 group by 的 sum()、count()、avg()、min()、max()插入多行,验证聚合结果
空值处理coalesce(field, 'default')、空值安全表达式插入字段为空的行,验证默认值
参数with parameters p_param : type使用参数调用视图,验证筛选结果
货币/单位转换currency_conversion()、unit_conversion()插入转换数据,验证结果
字符串操作concat()、substring()、length()插入字符串值,验证输出
关联association [0..*] to ...在两侧插入数据,验证导航
向用户输出

将识别出的测试用例以编号列表形式呈现:

Identified test cases for ZI_SALESORDER:

1. [CALCULATION] test_net_amount_calculation — Verify net_amount = gross_amount - discount
2. [CASE] test_status_text_open — Verify status 'O' maps to 'Open'
3. [CASE] test_status_text_closed — Verify status 'C' maps to 'Closed'
4. [JOIN] test_customer_join — Verify customer data is correctly joined
5. [WHERE] test_active_orders_filter — Verify only active orders are returned
6. [NULL] test_description_coalesce — Verify null description gets default value

询问用户:“要生成哪些测试用例?(全部/指定编号/跳过哪些?)”

如果用户回答“全部”或未说明偏好,则生成全部用例。

步骤 3:获取 CDS 测试替身框架参考资料

使用 mcp-sap-docs 获取最新的 CDS 测试替身框架模式,确保生成的代码遵循 SAP 最佳实践。

search("CDS test double framework cl_cds_test_environment")

还要获取:

search("ABAP Unit cl_abap_unit_assert")

使用返回的文档来确定生成代码的模式。需要核实的关键内容:

  • cl_cds_test_environment=>create() 的正确签名
  • 正确的 get_double()/insert() 模式
  • 正确的断言方法名称

步骤 4:生成测试类

按照以下结构生成完整的 ABAP 测试类:

模板
"! @testing <CDS_ENTITY_NAME>
CLASS <test_class_name> DEFINITION
  PUBLIC FINAL
  FOR TESTING
  DURATION SHORT
  RISK LEVEL HARMLESS.

  PUBLIC SECTION.
  PROTECTED SECTION.
  PRIVATE SECTION.
    CLASS-DATA environment TYPE REF TO if_cds_test_environment.

    CLASS-METHODS class_setup    RAISING cx_static_check.
    CLASS-METHODS class_teardown.
    METHODS setup.

    "! <description of test case 1>
    METHODS <test_method_1> FOR TESTING RAISING cx_static_check.
    "! <description of test case 2>
    METHODS <test_method_2> FOR TESTING RAISING cx_static_check.
    " ... one method per selected test case
ENDCLASS.

CLASS <test_class_name> IMPLEMENTATION.

  METHOD class_setup.
    environment = cl_cds_test_environment=>create( i_for_entity = '<CDS_ENTITY_NAME>' ).
  ENDMETHOD.

  METHOD class_teardown.
    environment->destroy( ).
  ENDMETHOD.

  METHOD setup.
    environment->clear_doubles( ).
  ENDMETHOD.

  METHOD <test_method_1>.
    " Arrange — prepare test data for underlying tables
    DATA lt_<table> TYPE STANDARD TABLE OF <underlying_table> WITH EMPTY KEY.
    lt_<table> = VALUE #(
      ( <field1> = '<value1>' <field2> = '<value2>' ... )
    ).
    environment->get_double( '<UNDERLYING_TABLE>' )->insert( lt_<table> ).

    " Act — SELECT from the CDS entity under test
    SELECT * FROM <cds_entity> INTO TABLE @DATA(lt_result).

    " Assert — verify expected behavior
    cl_abap_unit_assert=>assert_equals(
      act = lines( lt_result )
      exp = <expected_count>
      msg = |Expected { <expected_count> } rows| ).

    cl_abap_unit_assert=>assert_equals(
      act = lt_result[ 1 ]-<field>
      exp = '<expected_value>'
      msg = '<assertion message>' ).
  ENDMETHOD.

  " ... more test methods

ENDCLASS.
测试数据生成规则

生成测试数据时,请遵循以下原则:

  1. 最少行数:使用尽可能少的行来测试该语义。通常每项测试使用 1~3 行。
  2. 直观的值:选择能轻松验证预期结果的值:
    • 对于 gross - discount = net:使用 100.00 - 10.00 = 90.00,而不是 37.83 - 4.27
    • 对于 CASE 分支:使用 CASE 表达式中的确切值
    • 对于 WHERE 筛选:一行符合条件,另一行不符合
  3. 类型正确:严格匹配 ABAP 类型:
    • NUMC 字段使用 '001'(带前导零的字符串)
    • DEC/CURR 字段使用 '100.00'
    • DATS 字段使用 '20260101'
    • CUKY 字段使用 'EUR'
  4. 填充键字段:始终填充键字段,即使测试不会直接检查这些字段
  5. 结果确定:绝不使用随机值或依赖日期的值
  6. 相互独立:每个测试方法都应自成一体(在 setup 中使用 clear_doubles 确保这一点)
命名约定
  • 测试类:ZCL_TEST_<ENTITY> 或 ZCL_<ENTITY>_TEST
  • 测试方法:test_<semantic>_<detail>(例如,test_status_case_open、test_net_amount_calc)
  • 方法名使用 snake_case(ABAP 测试方法的约定)
  • 方法名长度不超过 30 个字符

步骤 5:预览并确认

向用户展示生成的完整测试类源代码,并询问:

“这是生成的测试类。要在 SAP 系统上创建它吗?(是/先编辑/取消)”

如果用户需要修改,请先完成修改,再继续操作。

步骤 6:创建、激活并测试

6-pre. 对生成的代码进行 Lint 检查(可选)

编写之前,根据 Lint 规则验证生成的代码:

SAPLint(action="lint", source="<generated_source>", name="<test_class_name>")

继续之前,请修复所有 Lint 检查结果。启用预写入 Lint 验证后,也会自动运行(默认:开启)。

6a. 创建测试类
SAPWrite(action="create", type="CLAS", name="<test_class_name>", source="<generated_source>", package="<package>", transport="<transport>")
6b. 更新源代码(如果 create 仅生成框架)
SAPWrite(action="update", type="CLAS", name="<test_class_name>", source="<generated_source>", transport="<transport>")
6c. 激活测试类
SAPActivate(type="CLAS", name="<test_class_name>")

激活会返回结构化响应,其中包含详细的错误/警告信息(包括行号)。请利用这些信息准确定位问题。

6d. 运行单元测试
SAPDiagnose(action="unittest", type="CLAS", name="<test_class_name>")
6e. 报告结果

向用户展示:

  • 通过/失败/跳过的测试数量
  • 对于任何失败:断言消息以及失败的测试方法
  • 对于任何失败:建议的修复方法

如果测试失败:

  1. 分析失败消息
  2. 判断问题出在测试数据、断言还是 CDS 逻辑
  3. 使用 SAPWrite(action="edit_method", ...) 修复测试方法
  4. 重新激活并再次运行

错误处理

常见问题及修复方法
错误原因修复方法
CX_CDS_TEST_ENVIRONMENT 在 class_setup 期间出现实体名称错误或未激活验证实体名称,检查激活状态
VALUE 构造器中的类型不匹配测试数据中的字段类型错误检查 DD03L 或表结构以确认正确类型
GET_DOUBLE 无法处理某个数据源数据源名称不匹配检查 CDS DDL 中准确的数据源名称(区分大小写!)
断言失败且出现意外值测试数据或预期结果错误重新检查 CDS 逻辑,调整测试数据或断言
激活错误:“未找到测试关系”@testing 注解指向了错误的实体修复 "! @testing 注释中的实体名称
类已存在测试类已创建改用 SAPWrite(action="update", ...)

说明

BTP 与本地部署的差异
  • BTP:只能创建 Z*/Y* 类。无法通过 DD03L 查询标准 SAP 表。请使用已发布的 CDS 实体进行类型引用。
  • 本地部署:可完全访问 DD03L、DD02L 中的字段目录。可查询 TADIR 以检查对象是否存在。
此 Skill 不会执行的操作
  • 性能测试:CDS 测试替身用于逻辑测试,而非性能测试
  • 授权测试:DCL/CDS 访问控制测试需要单独的模式
  • 集成测试:此功能生成隔离的单元测试,而非端到端流程
  • RAP 行为测试:对于验证、操作/确定逻辑,请改用 RAP BO 测试替身框架
何时使用此 Skill
  • CDS 实体包含非平凡逻辑(计算、CASE、筛选、联接)时
  • 用户希望以基础测试覆盖率作为起点时
  • 重构 CDS 逻辑并希望添加回归测试时
  • 不适用于仅重命名字段的简单投影 — 如果第 2 步的分析发现没有可测试语义(只有字段重命名,没有计算、CASE、WHERE、JOIN 或聚合),请提醒用户:“此 CDS 视图只是一个简单投影,不包含可测试逻辑。单元测试只能验证字段是否正确设置别名,价值有限。建议改为测试底层视图。”

评论

支持 Markdown