abapgit-agent 1.5.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/abap/guidelines/00_index.md +36 -0
- package/abap/guidelines/01_sql.md +88 -0
- package/abap/guidelines/02_exceptions.md +176 -0
- package/abap/guidelines/03_testing.md +269 -0
- package/abap/guidelines/04_cds.md +136 -0
- package/abap/guidelines/05_classes.md +58 -0
- package/abap/guidelines/06_objects.md +110 -0
- package/abap/guidelines/07_json.md +24 -0
- package/abap/guidelines/08_abapgit.md +222 -0
- package/abap/guidelines/09_unit_testable_code.md +568 -0
- package/bin/abapgit-agent +513 -38
- package/bin/abgagt +24 -0
- package/package.json +8 -2
- package/src/abap-client.js +65 -2
- package/src/agent.js +57 -3
- package/src/config.js +1 -1
- package/src/ref-search.js +1037 -0
- package/.abapGitAgent.example +0 -11
- package/.github/workflows/release.yml +0 -60
- package/API.md +0 -710
- package/CLAUDE.md +0 -1058
- package/CLAUDE_MEM.md +0 -88
- package/ERROR_HANDLING.md +0 -30
- package/INSTALL.md +0 -155
- package/RELEASE_NOTES.md +0 -143
- package/abap/CLAUDE.md +0 -1010
- package/abap/copilot-instructions.md +0 -79
- package/abap/package.devc.xml +0 -10
- package/abap/zcl_abgagt_agent.clas.abap +0 -420
- package/abap/zcl_abgagt_agent.clas.xml +0 -15
- package/abap/zcl_abgagt_cmd_factory.clas.abap +0 -48
- package/abap/zcl_abgagt_cmd_factory.clas.xml +0 -15
- package/abap/zcl_abgagt_command_create.clas.abap +0 -95
- package/abap/zcl_abgagt_command_create.clas.xml +0 -15
- package/abap/zcl_abgagt_command_import.clas.abap +0 -138
- package/abap/zcl_abgagt_command_import.clas.xml +0 -15
- package/abap/zcl_abgagt_command_inspect.clas.abap +0 -456
- package/abap/zcl_abgagt_command_inspect.clas.testclasses.abap +0 -121
- package/abap/zcl_abgagt_command_inspect.clas.xml +0 -16
- package/abap/zcl_abgagt_command_preview.clas.abap +0 -386
- package/abap/zcl_abgagt_command_preview.clas.xml +0 -15
- package/abap/zcl_abgagt_command_pull.clas.abap +0 -80
- package/abap/zcl_abgagt_command_pull.clas.testclasses.abap +0 -87
- package/abap/zcl_abgagt_command_pull.clas.xml +0 -16
- package/abap/zcl_abgagt_command_tree.clas.abap +0 -237
- package/abap/zcl_abgagt_command_tree.clas.xml +0 -15
- package/abap/zcl_abgagt_command_unit.clas.abap +0 -297
- package/abap/zcl_abgagt_command_unit.clas.xml +0 -15
- package/abap/zcl_abgagt_command_view.clas.abap +0 -240
- package/abap/zcl_abgagt_command_view.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_create.clas.abap +0 -71
- package/abap/zcl_abgagt_resource_create.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_health.clas.abap +0 -25
- package/abap/zcl_abgagt_resource_health.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_import.clas.abap +0 -66
- package/abap/zcl_abgagt_resource_import.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_inspect.clas.abap +0 -63
- package/abap/zcl_abgagt_resource_inspect.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_preview.clas.abap +0 -67
- package/abap/zcl_abgagt_resource_preview.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_pull.clas.abap +0 -71
- package/abap/zcl_abgagt_resource_pull.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_tree.clas.abap +0 -70
- package/abap/zcl_abgagt_resource_tree.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_unit.clas.abap +0 -64
- package/abap/zcl_abgagt_resource_unit.clas.xml +0 -15
- package/abap/zcl_abgagt_resource_view.clas.abap +0 -68
- package/abap/zcl_abgagt_resource_view.clas.xml +0 -15
- package/abap/zcl_abgagt_rest_handler.clas.abap +0 -32
- package/abap/zcl_abgagt_rest_handler.clas.xml +0 -15
- package/abap/zcl_abgagt_util.clas.abap +0 -93
- package/abap/zcl_abgagt_util.clas.testclasses.abap +0 -84
- package/abap/zcl_abgagt_util.clas.xml +0 -16
- package/abap/zcl_abgagt_viewer_clas.clas.abap +0 -58
- package/abap/zcl_abgagt_viewer_clas.clas.xml +0 -15
- package/abap/zcl_abgagt_viewer_ddls.clas.abap +0 -83
- package/abap/zcl_abgagt_viewer_ddls.clas.xml +0 -15
- package/abap/zcl_abgagt_viewer_dtel.clas.abap +0 -98
- package/abap/zcl_abgagt_viewer_dtel.clas.xml +0 -15
- package/abap/zcl_abgagt_viewer_factory.clas.abap +0 -41
- package/abap/zcl_abgagt_viewer_factory.clas.xml +0 -15
- package/abap/zcl_abgagt_viewer_intf.clas.abap +0 -58
- package/abap/zcl_abgagt_viewer_intf.clas.xml +0 -15
- package/abap/zcl_abgagt_viewer_stru.clas.abap +0 -59
- package/abap/zcl_abgagt_viewer_stru.clas.xml +0 -15
- package/abap/zcl_abgagt_viewer_tabl.clas.abap +0 -59
- package/abap/zcl_abgagt_viewer_tabl.clas.xml +0 -15
- package/abap/zcl_abgagt_viewer_ttyp.clas.abap +0 -93
- package/abap/zcl_abgagt_viewer_ttyp.clas.xml +0 -15
- package/abap/zif_abgagt_agent.intf.abap +0 -53
- package/abap/zif_abgagt_agent.intf.xml +0 -15
- package/abap/zif_abgagt_cmd_factory.intf.abap +0 -7
- package/abap/zif_abgagt_cmd_factory.intf.xml +0 -15
- package/abap/zif_abgagt_command.intf.abap +0 -26
- package/abap/zif_abgagt_command.intf.xml +0 -15
- package/abap/zif_abgagt_util.intf.abap +0 -28
- package/abap/zif_abgagt_util.intf.xml +0 -15
- package/abap/zif_abgagt_viewer.intf.abap +0 -12
- package/abap/zif_abgagt_viewer.intf.xml +0 -15
- package/docs/commands.md +0 -142
- package/docs/create-command.md +0 -129
- package/docs/health-command.md +0 -89
- package/docs/import-command.md +0 -195
- package/docs/init-command.md +0 -189
- package/docs/inspect-command.md +0 -169
- package/docs/list-command.md +0 -289
- package/docs/preview-command.md +0 -528
- package/docs/pull-command.md +0 -202
- package/docs/status-command.md +0 -68
- package/docs/tree-command.md +0 -303
- package/docs/unit-command.md +0 -167
- package/docs/view-command.md +0 -501
- package/img/claude.png +0 -0
- package/scripts/claude-integration.js +0 -351
- package/scripts/release.js +0 -298
- package/scripts/release.sh +0 -60
- package/scripts/test-integration.js +0 -139
- package/scripts/unrelease.js +0 -277
package/README.md
CHANGED
|
@@ -154,6 +154,7 @@ npm run pull -- --url <git-url> --branch main
|
|
|
154
154
|
| tree Command | [docs/tree-command.md](docs/tree-command.md) |
|
|
155
155
|
| view Command | [docs/view-command.md](docs/view-command.md) |
|
|
156
156
|
| preview Command | [docs/preview-command.md](docs/preview-command.md) |
|
|
157
|
+
| ref Command | [docs/ref-command.md](docs/ref-command.md) |
|
|
157
158
|
| REST API Reference | [API.md](API.md) |
|
|
158
159
|
| Error Handling | [ERROR_HANDLING.md](ERROR_HANDLING.md) |
|
|
159
160
|
| ABAP Coding Guidelines | [abap/CLAUDE.md](abap/CLAUDE.md) |
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# ABAP Coding Guidelines Index
|
|
2
|
+
|
|
3
|
+
This folder contains detailed ABAP coding guidelines that can be searched using the `ref` command.
|
|
4
|
+
|
|
5
|
+
## Guidelines Available
|
|
6
|
+
|
|
7
|
+
| File | Topic |
|
|
8
|
+
|------|-------|
|
|
9
|
+
| `01_sql.md` | ABAP SQL Best Practices |
|
|
10
|
+
| `02_exceptions.md` | Exception Handling |
|
|
11
|
+
| `03_testing.md` | Unit Testing (including CDS) |
|
|
12
|
+
| `04_cds.md` | CDS Views |
|
|
13
|
+
| `05_classes.md` | ABAP Classes and Objects |
|
|
14
|
+
| `06_objects.md` | Object Naming Conventions |
|
|
15
|
+
| `07_json.md` | JSON Handling |
|
|
16
|
+
| `08_abapgit.md` | abapGit XML Metadata Templates |
|
|
17
|
+
| `09_unit_testable_code.md` | Unit Testable Code Guidelines (Dependency Injection) |
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
These guidelines are automatically searched by the `ref` command:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Search across all guidelines
|
|
25
|
+
abapgit-agent ref "CORRESPONDING"
|
|
26
|
+
|
|
27
|
+
# List all topics
|
|
28
|
+
abapgit-agent ref --list-topics
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Adding Custom Guidelines
|
|
32
|
+
|
|
33
|
+
To add your own guidelines:
|
|
34
|
+
1. Create a new `.md` file in this folder
|
|
35
|
+
2. Follow the naming convention: `XX_name.md`
|
|
36
|
+
3. Export to reference folder: `abapgit-agent ref export`
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ABAP SQL Best Practices
|
|
2
|
+
|
|
3
|
+
**Searchable keywords**: SELECT, FROM, WHERE, ABAP SQL, Open SQL, host variable, @ prefix, range table, INTO, UP TO, OFFSET, GROUP BY, JOIN
|
|
4
|
+
|
|
5
|
+
When writing ABAP SQL (Open SQL) queries, follow these rules:
|
|
6
|
+
|
|
7
|
+
## TOPICS IN THIS FILE
|
|
8
|
+
1. Host Variables (@ prefix) - line 5
|
|
9
|
+
2. Range Tables (IN clause) - line 17
|
|
10
|
+
3. SELECT Clause Order - line 35
|
|
11
|
+
4. Fixed Point Arithmetic - line 52
|
|
12
|
+
5. Field Separation - line 62
|
|
13
|
+
|
|
14
|
+
## 1. Host Variables - Use @ Prefix
|
|
15
|
+
|
|
16
|
+
Use `@` prefix for host variables in ABAP SQL:
|
|
17
|
+
|
|
18
|
+
```abap
|
|
19
|
+
" Correct
|
|
20
|
+
SELECT * FROM tadir WHERE devclass = @lv_package.
|
|
21
|
+
|
|
22
|
+
" Wrong - no @ prefix
|
|
23
|
+
SELECT * FROM tadir WHERE devclass = lv_package.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 2. Range Tables for IN Clauses
|
|
27
|
+
|
|
28
|
+
When filtering with `IN`, use a range table with `@` prefix:
|
|
29
|
+
|
|
30
|
+
```abap
|
|
31
|
+
" Define range table
|
|
32
|
+
DATA lt_type_range TYPE RANGE OF tadir-object.
|
|
33
|
+
ls_type-sign = 'I'.
|
|
34
|
+
ls_type-option = 'EQ'.
|
|
35
|
+
ls_type-low = 'CLAS'.
|
|
36
|
+
APPEND ls_type TO lt_type_range.
|
|
37
|
+
|
|
38
|
+
" Use with @ prefix
|
|
39
|
+
SELECT object, obj_name FROM tadir
|
|
40
|
+
WHERE object IN @lt_type_range
|
|
41
|
+
INTO TABLE @lt_objects.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 3. SELECT Statement Clause Order
|
|
45
|
+
|
|
46
|
+
The correct sequence is:
|
|
47
|
+
```
|
|
48
|
+
SELECT → FROM → WHERE → ORDER BY → INTO → UP TO → OFFSET
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```abap
|
|
52
|
+
SELECT object, obj_name FROM tadir
|
|
53
|
+
WHERE devclass = @lv_package
|
|
54
|
+
AND object IN @lt_type_range
|
|
55
|
+
ORDER BY object, obj_name
|
|
56
|
+
INTO TABLE @lt_objects
|
|
57
|
+
UP TO @lv_limit ROWS
|
|
58
|
+
OFFSET @lv_offset.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 4. Fixed Point Arithmetic (FIXPT)
|
|
62
|
+
|
|
63
|
+
For numeric operations in ABAP SQL (especially with UP TO/OFFSET), enable FIXPT in the class XML:
|
|
64
|
+
|
|
65
|
+
```xml
|
|
66
|
+
<VSEOCLASS>
|
|
67
|
+
<FIXPT>X</FIXPT>
|
|
68
|
+
</VSEOCLASS>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 5. Field Separation
|
|
72
|
+
|
|
73
|
+
Always separate fields with commas in SELECT:
|
|
74
|
+
|
|
75
|
+
```abap
|
|
76
|
+
" Correct
|
|
77
|
+
SELECT object, obj_name FROM tadir ...
|
|
78
|
+
|
|
79
|
+
" Wrong - missing comma
|
|
80
|
+
SELECT object obj_name FROM tadir ...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## See Also
|
|
86
|
+
- **Constructor Expressions** (05_classes.md) - for VALUE #(), FILTER, FOR loops
|
|
87
|
+
- **Internal Tables** - for filtering and iteration patterns
|
|
88
|
+
- **abapGit** (08_abapgit.md) - for XML metadata templates
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Exception Handling - Classical vs Class-Based
|
|
2
|
+
|
|
3
|
+
**Searchable keywords**: exception, RAISING, TRY, CATCH, cx_static_check, cx_dynamic_check, EXCEPTIONS, sy-subrc, class-based exception, classical exception
|
|
4
|
+
|
|
5
|
+
## TOPICS IN THIS FILE
|
|
6
|
+
1. Quick Identification - line 5
|
|
7
|
+
2. Classical Exceptions - line 12
|
|
8
|
+
3. Class-Based Exceptions - line 25
|
|
9
|
+
4. Method Signatures - line 50
|
|
10
|
+
5. Best Practices - line 80
|
|
11
|
+
6. Interface vs Class Methods - line 118
|
|
12
|
+
|
|
13
|
+
ABAP has two exception handling mechanisms. Using the wrong one causes silent failures.
|
|
14
|
+
|
|
15
|
+
## Quick Identification
|
|
16
|
+
|
|
17
|
+
| Method Signature | Exception Type | Handling Pattern |
|
|
18
|
+
|-----------------|----------------|------------------|
|
|
19
|
+
| `EXCEPTIONS exc = 1` | Classical | `sy-subrc` check |
|
|
20
|
+
| `RAISING cx_...` | Class-based | `TRY-CATCH` |
|
|
21
|
+
|
|
22
|
+
## Classical Exceptions (Old Style)
|
|
23
|
+
|
|
24
|
+
Methods declared with `EXCEPTIONS` in signature:
|
|
25
|
+
|
|
26
|
+
```abap
|
|
27
|
+
" Method declaration
|
|
28
|
+
class-methods describe_by_name
|
|
29
|
+
importing p_name type any
|
|
30
|
+
returning value(p_descr_ref) type ref to cl_abap_typedescr
|
|
31
|
+
exceptions
|
|
32
|
+
type_not_found. " <- Classical!
|
|
33
|
+
|
|
34
|
+
" Calling with classical exception
|
|
35
|
+
cl_abap_structdescr=>describe_by_name(
|
|
36
|
+
EXPORTING
|
|
37
|
+
p_name = iv_tabname
|
|
38
|
+
RECEIVING
|
|
39
|
+
p_descr_ref = lo_descr
|
|
40
|
+
EXCEPTIONS
|
|
41
|
+
type_not_found = 1
|
|
42
|
+
OTHERS = 2 ).
|
|
43
|
+
IF sy-subrc <> 0.
|
|
44
|
+
" Handle error
|
|
45
|
+
ENDIF.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Common classical exception methods:**
|
|
49
|
+
- `cl_abap_structdescr=>describe_by_name` - `type_not_found`
|
|
50
|
+
- `cl_abap_tabledescr=>describe_by_name` - `type_not_found`
|
|
51
|
+
- Many RTTI (Run Time Type Information) methods
|
|
52
|
+
|
|
53
|
+
## Class-Based Exceptions (Modern)
|
|
54
|
+
|
|
55
|
+
Methods declared with `RAISING`:
|
|
56
|
+
|
|
57
|
+
```abap
|
|
58
|
+
" Method declaration
|
|
59
|
+
methods get_ref
|
|
60
|
+
importing p_name type string
|
|
61
|
+
returning value(p_ref) type ref to cl_ci_checkvariant
|
|
62
|
+
raising cx_ci_checkvariant. " <- Class-based!
|
|
63
|
+
|
|
64
|
+
" Calling with TRY-CATCH
|
|
65
|
+
TRY.
|
|
66
|
+
lo_variant = cl_ci_checkvariant=>get_ref( p_name = lv_variant ).
|
|
67
|
+
CATCH cx_ci_checkvariant INTO DATA(lx_error).
|
|
68
|
+
" Handle error
|
|
69
|
+
ENDTRY.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## The Mistake to Avoid
|
|
73
|
+
|
|
74
|
+
**WRONG**: Using TRY-CATCH for classical exceptions
|
|
75
|
+
```abap
|
|
76
|
+
" This does NOT catch type_not_found!
|
|
77
|
+
TRY.
|
|
78
|
+
lo_descr = cl_abap_structdescr=>describe_by_name( iv_name ).
|
|
79
|
+
CATCH cx_root. " Never reached!
|
|
80
|
+
ENDTRY.
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**CORRECT**: Use proper pattern for each type
|
|
84
|
+
```abap
|
|
85
|
+
" Classical - use sy-subrc
|
|
86
|
+
cl_abap_structdescr=>describe_by_name(
|
|
87
|
+
EXPORTING p_name = iv_name
|
|
88
|
+
RECEIVING p_descr_ref = lo_descr
|
|
89
|
+
EXCEPTIONS type_not_found = 1 ).
|
|
90
|
+
IF sy-subrc <> 0.
|
|
91
|
+
" Handle error
|
|
92
|
+
ENDIF.
|
|
93
|
+
|
|
94
|
+
" Class-based - use TRY-CATCH
|
|
95
|
+
TRY.
|
|
96
|
+
lo_obj = cl_ci_checkvariant=>get_ref( lv_name ).
|
|
97
|
+
CATCH cx_root INTO DATA(lx_error).
|
|
98
|
+
" Handle error
|
|
99
|
+
ENDTRY.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## How to Check Which to Use
|
|
103
|
+
|
|
104
|
+
Use the `view` command to check method signature:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
abapgit-agent view --objects CL_ABAP_STRUCTDESCR
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Look for:
|
|
111
|
+
- `exceptions TYPE_NOT_FOUND` → Classical (use `sy-subrc`)
|
|
112
|
+
- `raising CX_SY_RTTI` → Class-based (use `TRY-CATCH`)
|
|
113
|
+
|
|
114
|
+
Or search the cheat sheets:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
abapgit-agent ref --topic exceptions
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Interface vs Class Methods
|
|
121
|
+
|
|
122
|
+
### Interface Methods
|
|
123
|
+
|
|
124
|
+
Cannot add RAISING clause in the implementing class. Options:
|
|
125
|
+
|
|
126
|
+
1. Add RAISING to interface definition
|
|
127
|
+
2. Use TRY-CATCH in the implementation
|
|
128
|
+
|
|
129
|
+
```abap
|
|
130
|
+
" Interface definition - can add RAISING here
|
|
131
|
+
INTERFACE zif_example.
|
|
132
|
+
methods execute
|
|
133
|
+
importing is_param type data optional
|
|
134
|
+
returning value(rv_result) type string
|
|
135
|
+
raising cx_static_check.
|
|
136
|
+
ENDINTERFACE.
|
|
137
|
+
|
|
138
|
+
" Implementation - CANNOT add RAISING here
|
|
139
|
+
CLASS zcl_example DEFINITION.
|
|
140
|
+
INTERFACES zif_example.
|
|
141
|
+
ENDCLASS.
|
|
142
|
+
|
|
143
|
+
CLASS zcl_example IMPLEMENTATION.
|
|
144
|
+
METHOD zif_example~execute.
|
|
145
|
+
" Must handle cx_static_check here with TRY-CATCH
|
|
146
|
+
" or declare it in interface, not here
|
|
147
|
+
ENDMETHOD.
|
|
148
|
+
ENDCLASS.
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Class Methods
|
|
152
|
+
|
|
153
|
+
Can add RAISING clause to declare exceptions, allowing caller to handle in one place:
|
|
154
|
+
|
|
155
|
+
```abap
|
|
156
|
+
" Class method with RAISING clause
|
|
157
|
+
METHODS process_data
|
|
158
|
+
importing iv_data type string
|
|
159
|
+
returning value(rv_result) type string
|
|
160
|
+
raising cx_static_check.
|
|
161
|
+
|
|
162
|
+
" Caller can handle in one place
|
|
163
|
+
TRY.
|
|
164
|
+
lv_result = lo_obj->process_data( iv_data = 'test' ).
|
|
165
|
+
CATCH cx_static_check.
|
|
166
|
+
" Handle exception
|
|
167
|
+
ENDTRY.
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### When to Use Each
|
|
171
|
+
|
|
172
|
+
| Scenario | Recommendation |
|
|
173
|
+
|----------|----------------|
|
|
174
|
+
| Multiple callers need to handle exception | Add RAISING to method definition |
|
|
175
|
+
| Exception should be handled internally | Use TRY-CATCH in implementation |
|
|
176
|
+
| Interface method | Add RAISING to interface, or use TRY-CATCH in class |
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Unit Testing
|
|
2
|
+
|
|
3
|
+
**Searchable keywords**: unit test, AUnit, test class, cl_abap_unit_assert, FOR TESTING, setup, teardown, RISK LEVEL, DURATION, CDS test double, CL_CDS_TEST_ENVIRONMENT
|
|
4
|
+
|
|
5
|
+
## TOPICS IN THIS FILE
|
|
6
|
+
1. Local Test Classes - line 3
|
|
7
|
+
2. File Structure - line 5
|
|
8
|
+
3. Required Elements - line 16
|
|
9
|
+
4. Naming Conventions - line 48
|
|
10
|
+
5. CDS Test Doubles - line 94
|
|
11
|
+
6. CDS with Aggregations - line 178
|
|
12
|
+
|
|
13
|
+
## Unit Testing with Local Test Classes
|
|
14
|
+
|
|
15
|
+
### File Structure
|
|
16
|
+
|
|
17
|
+
For ABAP local unit tests, use a **separate file** with `.testclasses.abap` extension:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
abap/
|
|
21
|
+
zcl_my_class.clas.abap <- Main class (no test code)
|
|
22
|
+
zcl_my_class.clas.testclasses.abap <- Local test class
|
|
23
|
+
zcl_my_class.clas.xml <- XML with WITH_UNIT_TESTS = X
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Required Elements
|
|
27
|
+
|
|
28
|
+
1. **Test class file** (`zcl_my_class.clas.testclasses.abap`):
|
|
29
|
+
```abap
|
|
30
|
+
*"* use this source file for your test class implementation
|
|
31
|
+
*"* local test class
|
|
32
|
+
CLASS ltcl_zcl_my_class DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
|
|
33
|
+
PRIVATE SECTION.
|
|
34
|
+
DATA mo_cut TYPE REF TO zcl_my_class.
|
|
35
|
+
METHODS setup.
|
|
36
|
+
METHODS test_method1 FOR TESTING.
|
|
37
|
+
METHODS test_method2 FOR TESTING.
|
|
38
|
+
ENDCLASS.
|
|
39
|
+
|
|
40
|
+
CLASS ltcl_zcl_my_class IMPLEMENTATION.
|
|
41
|
+
METHOD setup.
|
|
42
|
+
CREATE OBJECT mo_cut.
|
|
43
|
+
ENDMETHOD.
|
|
44
|
+
METHOD test_method1.
|
|
45
|
+
" Test code using cl_abap_unit_assert
|
|
46
|
+
ENDMETHOD.
|
|
47
|
+
ENDCLASS.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
2. **XML metadata** (`zcl_my_class.clas.xml`):
|
|
51
|
+
```xml
|
|
52
|
+
<VSEOCLASS>
|
|
53
|
+
...
|
|
54
|
+
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
|
|
55
|
+
</VSEOCLASS>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Naming Conventions
|
|
59
|
+
|
|
60
|
+
- Test class name: `LTCL_ZCL_<CLASSNAME>` (e.g., `LTCL_ZCL_COMMAND_PULL`)
|
|
61
|
+
- Test methods: `TEST_<methodname> FOR TESTING` or simply `test_method FOR TESTING`
|
|
62
|
+
- Test file: `<classname>.clas.testclasses.abap`
|
|
63
|
+
|
|
64
|
+
### CRITICAL: Method Name Length Limit
|
|
65
|
+
|
|
66
|
+
**Test method names MUST NOT exceed 30 characters!**
|
|
67
|
+
|
|
68
|
+
```abap
|
|
69
|
+
" WRONG - 34 characters (syntax error)
|
|
70
|
+
METHODS test_execute_with_minimal_params FOR TESTING.
|
|
71
|
+
|
|
72
|
+
" CORRECT - 18 characters
|
|
73
|
+
METHODS test_exec_minimal FOR TESTING.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Examples of compliant names:
|
|
77
|
+
- `test_get_name` (13 chars)
|
|
78
|
+
- `test_exec_minimal` (18 chars)
|
|
79
|
+
- `test_exec_files` (16 chars)
|
|
80
|
+
- `test_interface` (15 chars)
|
|
81
|
+
|
|
82
|
+
### Common Assertions
|
|
83
|
+
|
|
84
|
+
```abap
|
|
85
|
+
cl_abap_unit_assert=>assert_equals( act = lv_actual exp = lv_expected msg = 'Error message' ).
|
|
86
|
+
cl_abap_unit_assert=>assert_not_initial( act = lv_data msg = 'Should not be initial' ).
|
|
87
|
+
cl_abap_unit_assert=>assert_bound( act = lo_ref msg = 'Should be bound' ).
|
|
88
|
+
cl_abap_unit_assert=>assert_true( act = lv_bool msg = 'Should be true' ).
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### What NOT To Do
|
|
92
|
+
|
|
93
|
+
- ❌ Don't add test methods directly in the main `.clas.abap` file
|
|
94
|
+
- ❌ Don't use `CLASS ... DEFINITION ...` without the special comment header
|
|
95
|
+
- ❌ Don't reference `<TESTCLASS>` in XML - abapGit auto-detects `.testclasses.abap`
|
|
96
|
+
- ❌ Don't use nested local classes inside the main class definition
|
|
97
|
+
|
|
98
|
+
### Running Tests
|
|
99
|
+
|
|
100
|
+
In ABAP: SE24 → Test → Execute Unit Tests
|
|
101
|
+
|
|
102
|
+
Or via abapGit: Pull the files and run tests in the ABAP system.
|
|
103
|
+
|
|
104
|
+
## Unit Testing CDS Views
|
|
105
|
+
|
|
106
|
+
When testing code that uses CDS view entities, you can use the **CDS Test Double Framework** (`CL_CDS_TEST_ENVIRONMENT`) to create test doubles for CDS views. This allows you to inject test data without affecting production data.
|
|
107
|
+
|
|
108
|
+
### When to Use CDS Test Doubles
|
|
109
|
+
|
|
110
|
+
- Testing code that reads from CDS views
|
|
111
|
+
- Need controlled test data (not production data)
|
|
112
|
+
- Testing CDS view logic with specific scenarios
|
|
113
|
+
|
|
114
|
+
### CDS Test Double Framework
|
|
115
|
+
|
|
116
|
+
Use `CL_CDS_TEST_ENVIRONMENT` for controlled test data:
|
|
117
|
+
|
|
118
|
+
```abap
|
|
119
|
+
"-------------------------
|
|
120
|
+
" CLASS DEFINITION
|
|
121
|
+
"-------------------------
|
|
122
|
+
CLASS ltcl_cds_test DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.
|
|
123
|
+
|
|
124
|
+
PRIVATE SECTION.
|
|
125
|
+
" IMPORTANT: Use interface type, not class type!
|
|
126
|
+
DATA mo_cds_env TYPE REF TO if_cds_test_environment.
|
|
127
|
+
|
|
128
|
+
" IMPORTANT: class_setup/teardown must be CLASS-METHODS (static)!
|
|
129
|
+
CLASS-DATA mo_cds_env_static TYPE REF TO if_cds_test_environment.
|
|
130
|
+
|
|
131
|
+
METHODS setup.
|
|
132
|
+
METHODS test_cds_with_doubles FOR TESTING.
|
|
133
|
+
|
|
134
|
+
CLASS-METHODS: class_setup,
|
|
135
|
+
class_teardown.
|
|
136
|
+
|
|
137
|
+
ENDCLASS.
|
|
138
|
+
|
|
139
|
+
"-------------------------
|
|
140
|
+
" CLASS IMPLEMENTATION
|
|
141
|
+
"-------------------------
|
|
142
|
+
CLASS ltcl_cds_test IMPLEMENTATION.
|
|
143
|
+
|
|
144
|
+
METHOD class_setup.
|
|
145
|
+
" Create CDS test environment - framework auto-creates doubles for dependencies
|
|
146
|
+
mo_cds_env_static = cl_cds_test_environment=>create(
|
|
147
|
+
i_for_entity = 'ZC_MY_CDS_VIEW' ).
|
|
148
|
+
ENDMETHOD.
|
|
149
|
+
|
|
150
|
+
METHOD class_teardown.
|
|
151
|
+
" Clean up test environment
|
|
152
|
+
mo_cds_env_static->destroy( ).
|
|
153
|
+
ENDMETHOD.
|
|
154
|
+
|
|
155
|
+
METHOD setup.
|
|
156
|
+
" IMPORTANT: Assign static env to instance and clear doubles
|
|
157
|
+
mo_cds_env = mo_cds_env_static.
|
|
158
|
+
mo_cds_env->clear_doubles( ).
|
|
159
|
+
ENDMETHOD.
|
|
160
|
+
|
|
161
|
+
METHOD test_cds_with_doubles.
|
|
162
|
+
" IMPORTANT: Must declare table type first, cannot inline in VALUE!
|
|
163
|
+
DATA lt_test_data TYPE TABLE OF zc_my_cds_view WITH EMPTY KEY.
|
|
164
|
+
lt_test_data = VALUE #(
|
|
165
|
+
( field1 = 'A' field2 = 100 )
|
|
166
|
+
( field1 = 'B' field2 = 200 ) ).
|
|
167
|
+
|
|
168
|
+
" Insert test data using named parameter
|
|
169
|
+
mo_cds_env->insert_test_data( i_data = lt_test_data ).
|
|
170
|
+
|
|
171
|
+
" Select from CDS view
|
|
172
|
+
SELECT * FROM zc_my_cds_view INTO TABLE @DATA(lt_result).
|
|
173
|
+
|
|
174
|
+
" Verify results
|
|
175
|
+
cl_abap_unit_assert=>assert_not_initial(
|
|
176
|
+
act = lt_result
|
|
177
|
+
msg = 'Result should not be empty' ).
|
|
178
|
+
|
|
179
|
+
cl_abap_unit_assert=>assert_equals(
|
|
180
|
+
act = lines( lt_result )
|
|
181
|
+
exp = 2
|
|
182
|
+
msg = 'Expected 2 rows' ).
|
|
183
|
+
ENDMETHOD.
|
|
184
|
+
|
|
185
|
+
ENDCLASS.
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Testing CDS Views with Aggregations (SUM, COUNT, GROUP BY)
|
|
189
|
+
|
|
190
|
+
For CDS views with aggregations, insert test data into the **base tables** (SFLIGHT, SCARR, SBOOK), not directly into the CDS view:
|
|
191
|
+
|
|
192
|
+
```abap
|
|
193
|
+
METHOD test_aggregation.
|
|
194
|
+
" Insert data into base tables via CDS test doubles
|
|
195
|
+
DATA lt_scarr TYPE TABLE OF scarr WITH EMPTY KEY.
|
|
196
|
+
lt_scarr = VALUE #( ( carrid = 'LH' carrname = 'Lufthansa' currcode = 'EUR' ) ).
|
|
197
|
+
mo_cds_env->insert_test_data( i_data = lt_scarr ).
|
|
198
|
+
|
|
199
|
+
DATA lt_sflight TYPE TABLE OF sflight WITH EMPTY KEY.
|
|
200
|
+
lt_sflight = VALUE #( ( carrid = 'LH' connid = '0400' fldate = '20240115'
|
|
201
|
+
seatsmax = 200 seatsocc = 100 ) ).
|
|
202
|
+
mo_cds_env->insert_test_data( i_data = lt_sflight ).
|
|
203
|
+
|
|
204
|
+
DATA lt_sbook TYPE TABLE OF sbook WITH EMPTY KEY.
|
|
205
|
+
lt_sbook = VALUE #(
|
|
206
|
+
( carrid = 'LH' connid = '0400' fldate = '20240115' bookid = '0001' forcuram = 1000 )
|
|
207
|
+
( carrid = 'LH' connid = '0400' fldate = '20240115' bookid = '0002' forcuram = 2000 )
|
|
208
|
+
( carrid = 'LH' connid = '0400' fldate = '20240115' bookid = '0003' forcuram = 3000 ) ).
|
|
209
|
+
mo_cds_env->insert_test_data( i_data = lt_sbook ).
|
|
210
|
+
|
|
211
|
+
" Select from CDS view - aggregations will use test double data
|
|
212
|
+
SELECT * FROM zc_flight_revenue INTO TABLE @DATA(lt_result).
|
|
213
|
+
|
|
214
|
+
" Verify aggregations
|
|
215
|
+
cl_abap_unit_assert=>assert_equals(
|
|
216
|
+
exp = 3
|
|
217
|
+
act = lt_result[ 1 ]-numberofbookings
|
|
218
|
+
msg = 'Should have 3 bookings' ).
|
|
219
|
+
|
|
220
|
+
cl_abap_unit_assert=>assert_equals(
|
|
221
|
+
exp = '6000.00'
|
|
222
|
+
act = lt_result[ 1 ]-totalrevenue
|
|
223
|
+
msg = 'Total revenue should be 6000.00' ).
|
|
224
|
+
ENDMETHOD.
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Key Classes for CDS Testing
|
|
228
|
+
|
|
229
|
+
| Item | Type/Usage |
|
|
230
|
+
|------|------------|
|
|
231
|
+
| `CL_CDS_TEST_ENVIRONMENT` | Class with `CREATE` method |
|
|
232
|
+
| `IF_CDS_TEST_ENVIRONMENT` | Interface (CREATE returns this type) |
|
|
233
|
+
| `CLASS-METHODS` | `class_setup` and `class_teardown` must be static methods |
|
|
234
|
+
| `CL_OSQL_TEST_ENVIRONMENT` | Test doubles for database tables (use for aggregations) |
|
|
235
|
+
| `CL_ABAP_UNIT_ASSERT` | Assertions |
|
|
236
|
+
|
|
237
|
+
### Key Methods
|
|
238
|
+
|
|
239
|
+
| Method | Purpose |
|
|
240
|
+
|--------|---------|
|
|
241
|
+
| `CL_CDS_TEST_ENVIRONMENT=>create( i_for_entity = ... )` | Create test environment (returns `if_cds_test_environment`) |
|
|
242
|
+
| `insert_test_data( i_data = ... )` | Insert test data into test doubles |
|
|
243
|
+
| `clear_doubles` | Clear test data before each test method |
|
|
244
|
+
| `destroy` | Clean up after test class |
|
|
245
|
+
|
|
246
|
+
### Important Usage Notes
|
|
247
|
+
|
|
248
|
+
1. **Use interface type**: `DATA mo_cds_env TYPE REF TO if_cds_test_environment` - the CREATE method returns an interface reference
|
|
249
|
+
2. **CLASS-METHODS required**: `class_setup` and `class_teardown` must be declared with `CLASS-METHODS` (not `METHODS`)
|
|
250
|
+
3. **Table type declaration**: Must declare `DATA lt_tab TYPE TABLE OF <type> WITH EMPTY KEY` before using `VALUE #()`
|
|
251
|
+
4. **Auto-created dependencies**: CDS framework auto-creates test doubles for base tables - do not specify `i_dependency_list`
|
|
252
|
+
5. **Aggregations**: For CDS views with SUM/COUNT/GROUP BY, insert test data into base tables (SFLIGHT, SCARR, etc.)
|
|
253
|
+
6. **Clear doubles**: Call `clear_doubles` in `setup` method before each test
|
|
254
|
+
7. **Enable associations**: Set `test_associations = 'X'` only if testing CDS associations
|
|
255
|
+
8. **Exception handling**: Declare test methods with `RAISING cx_static_check` for proper exception handling
|
|
256
|
+
|
|
257
|
+
### Search Reference for More Details
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
abapgit-agent ref "cl_cds_test_environment"
|
|
261
|
+
abapgit-agent ref --topic unit-tests
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## See Also
|
|
267
|
+
- **CDS Views** (04_cds.md) - for CDS view definitions and syntax
|
|
268
|
+
- **abapGit** (08_abapgit.md) - for WITH_UNIT_TESTS in XML metadata
|
|
269
|
+
- **ABAP SQL** (01_sql.md) - for SELECT statements in tests
|