generate-cds-unit-test について
CDS Test Double Frameworkを使い、CDSエンティティ向けのABAP Unitテストクラスを生成するスキルです。CDSロジックを検証するABAP開発者向けに、意味解析からプレビュー、書き込み、検証までを扱います。
主な機能
- 01CDS定義、項目、依存関係の読み取り
- 02テスト可能なCDSセマンティクスの特定
- 03ABAP Unitテストクラスの生成
- 04Lint、アクティブ化、テスト実行
活用シーン
- 01計算やフィルターを含むCDSエンティティのテスト
- 02CDSリファクタリング時の回帰テスト作成
- 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 Test Double Framework を使用して、CDS エンティティの ABAP Unit テストクラスを生成します。
このスキルは、ARC-1(SAP システムアクセス)と mcp-sap-docs(ドキュメントとベストプラクティス)を組み合わせ、SAP Joule の「CDS Unit Test Generation」機能を再現します。
スマートデフォルト(暗黙的に適用し、質問しないでください)
| 設定 | デフォルト | 理由 |
|---|---|---|
| テストクラス名 | ZCL_TEST_<entity_name> | 標準的な命名規則 |
| パッケージ | $TMP | 迅速なプロトタイピング |
| テスト範囲 | テスト可能なすべてのセマンティクス | 一覧を確認した後、ユーザーが範囲を絞り込めます |
| リスクレベル | HARMLESS | CDS テストダブルは実データを変更しません |
| 期間 | SHORT | 単体テストは高速であるべきです |
入力
ユーザーは CDS エンティティ名(例:ZI_SALESORDER、ZC_TRAVEL)を指定します。
必要なのは CDS エンティティ名 だけです。ユーザーがエンティティ名のみを指定した場合は、スマートデフォルトを適用してすぐに進めてください。
任意で、ユーザーは次の項目を指定できます。
- テストクラス名(デフォルト:
ZCL_TEST_<entity_name>) - パッケージ(デフォルト:
$TMP) - 移送依頼(
$TMP以外のパッケージの場合のみ必要)
ステップ 1:CDS エンティティのコンテキストを収集する
CDS エンティティ、そのフィールド構造、およびすべての依存関係を、ツール呼び出し 3 回だけで読み取ります。
1a. CDS DDL ソースを読み取る
SAPRead(type="DDLS", name="<entity_name>")
1b. 構造化されたフィールド一覧を取得する
SAPRead(type="DDLS", name="<entity_name>", include="elements")
キーのマーカー、エイリアス、アソシエーション参照、式の種類(計算、CASE、キャスト、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 Test Double Framework と同じエンジンです。
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 | 分岐ごとに 1 つのテスト |
| 型変換 | 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 | フィルター条件に一致するデータと、一致しないデータを挿入する |
| JOIN | inner join、left outer join、association | 両方のテーブルに一致するキーを挿入する。外部結合では、一致しないキーも使ってテストする |
| 集計 | group by を使った sum()、count()、avg()、min()、max() | 複数の行を挿入し、集計結果を検証する |
| NULL の処理 | coalesce(field, 'default')、NULL セーフな式 | フィールドが NULL の行を挿入し、デフォルト値を検証する |
| パラメーター | 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 Test Double Framework のリファレンスを取得する
mcp-sap-docs を使って、最新の CDS Test Double Framework のパターンを取得します。これにより、生成するコードが 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~3 行です。
- 分かりやすい値:期待される結果を簡単に検証できる値を選びます。
gross - discount = netの場合:37.83 - 4.27 ではなく、100.00 - 10.00 = 90.00 を使う- CASE の分岐の場合:CASE 式に記述された値をそのまま使う
- WHERE フィルターの場合:条件に一致する行を 1 行、一致しない行を 1 行使う
- 型の一致:ABAP の型に正確に合わせます。
- NUMC フィールドには
'001'(先頭にゼロを付けた文字列)を使う - DEC/CURR フィールドには
'100.00'を使う - DATS フィールドには
'20260101'を使う - CUKY フィールドには
'EUR'を使う
- NUMC フィールドには
- キー項目を設定する:直接テストしない場合でも、必ずキー項目に値を設定します。
- 決定性:ランダムな値や日付に依存する値は使いません。
- 独立性:各テストメソッドは自己完結させます(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. 生成したコードをリントチェックする(任意)
書き込む前に、生成したコードがリントルールに準拠しているか検証します。
SAPLint(action="lint", source="<generated_source>", name="<test_class_name>")
作業を続ける前に、リントで検出された問題を修正してください。事前のリント検証は、有効にすると(デフォルト:オン)自動的にも実行されます。
6a. テストクラスを作成する
SAPWrite(action="create", type="CLAS", name="<test_class_name>", source="<generated_source>", package="<package>", transport="<transport>")
6b. ソースを更新する(作成時にスキャフォールドのみが生成される場合)
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. 結果を報告する
次の内容をユーザーに示してください。
- 成功/失敗/スキップしたテストの数
- 失敗がある場合:アサーションメッセージと、失敗したテストメソッド
- 失敗に対する修正案
テストが失敗した場合:
- 失敗メッセージを分析します
- テストデータ、アサーション、CDS ロジックのどれに問題があるかを特定します
SAPWrite(action="edit_method", ...)を使ってテストメソッドを修正します- 再度有効化して実行します
エラー処理
よくある問題と修正方法
| エラー | 原因 | 修正方法 |
|---|---|---|
class_setup 中の CX_CDS_TEST_ENVIRONMENT | エンティティ名が誤っているか、有効化されていない | エンティティ名を確認し、有効化ステータスを確認します |
| VALUE コンストラクターで型が一致しない | テストデータのフィールド型が誤っている | DD03L またはテーブル構造で正しい型を確認します |
データソースに対する GET_DOUBLE が失敗する | データソース名が一致しない | CDS DDL で正確なデータソース名を確認します(大文字と小文字を区別します!) |
| 予期しない値でアサーションが失敗する | テストデータまたは期待値が誤っている | CDS ロジックを再確認し、テストデータまたはアサーションを調整します |
| 有効化エラー:「test relation not found」 | @testing アノテーションが誤ったエンティティを指している | "! @testing コメント内のエンティティ名を修正します |
| クラスがすでに存在する | テストクラスがすでに作成されている | 代わりに SAPWrite(action="update", ...) を使います |
注意事項
BTP とオンプレミスの違い
- BTP:作成できるのは Z*/Y* クラスのみです。標準 SAP テーブルは DD03L 経由でクエリできません。型の参照にはリリース済み CDS エンティティを使ってください。
- オンプレミス:フィールドカタログの DD03L、DD02L にフルアクセスできます。オブジェクトの存在確認には TADIR をクエリできます。
このスキルで対応しないこと
- パフォーマンステスト:CDS テストダブルはロジックのテスト用であり、パフォーマンスのテスト用ではありません
- 権限テスト:DCL/CDS のアクセス制御テストには別のパターンが必要です
- 統合テスト:生成されるのは分離された単体テストであり、エンドツーエンドのフローではありません
- RAP の振る舞いテスト:バリデーション/アクション/判定には、代わりに RAP BO Test Double Framework を使ってください
このスキルを使う場面
- CDS エンティティに複雑なロジック(計算、CASE、フィルター、結合)が含まれている場合
- ユーザーが基本的なテストカバレッジを出発点として求めている場合
- CDS ロジックをリファクタリングし、回帰テストを作成する場合
- 単純なフィールド名変更だけのプロジェクションには使わないでください。ステップ 2 の分析でテスト可能な意味論が見つからない場合(計算、CASE、WHERE、JOIN、集計を含まず、フィールド名の変更だけの場合)は、ユーザーに次のように警告してください:"この CDS ビューは、テスト可能なロジックを含まない単純なプロジェクションです。単体テストではフィールドのエイリアスが正しいことしか検証できず、得られる価値は最小限です。代わりに基盤となるビューのテストを検討してください。"