Fix coverage with several contract classes; table annotation and file path checks; clean task dir on write

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
Kral
2026-10-03 08:44:35 +02:00
parent fb576b0954
commit 03ab36149e
388 changed files with 28620 additions and 339 deletions

View File

@@ -0,0 +1,29 @@
{
"id": "G0128",
"pool": "eval",
"object_type": "CLAS",
"category": "D",
"attempts": [
{
"stage": "validate",
"oracle": 0,
"null": 0
},
{
"stage": "validate",
"oracle": 92.5,
"null": 0
},
{
"stage": "validate",
"oracle": 92.5,
"null": 0
},
{
"stage": "validate",
"oracle": 92.5,
"null": 0
}
],
"accepted": false
}

View File

@@ -0,0 +1,172 @@
CLASS {{p}}crew_check_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
TYPES ty_hours TYPE p LENGTH 4 DECIMALS 1.
DATA mo_cut TYPE REF TO {{p}}crew_duty_check.
METHODS setup.
METHODS base_duty
RETURNING VALUE(rs_duty) TYPE {{p}}crew_duty_check=>ty_duty.
METHODS valid_duty_passes FOR TESTING.
METHODS licence_invalid FOR TESTING.
METHODS rating_missing FOR TESTING.
METHODS rest_too_short FOR TESTING.
METHODS duty_too_long FOR TESTING.
METHODS month_limit FOR TESTING.
METHODS first_rule_wins FOR TESTING.
METHODS rating_before_rest FOR TESTING.
METHODS boundary_values FOR TESTING.
METHODS month_limit_exact FOR TESTING.
ENDCLASS.
CLASS {{p}}crew_check_hidden IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}crew_duty_check( ).
ENDMETHOD.
METHOD base_duty.
CLEAR rs_duty.
rs_duty-crew_id = 'C0001'.
rs_duty-licence_valid = abap_true.
rs_duty-type_rating = 'A320'.
rs_duty-aircraft_type = 'A320'.
rs_duty-rest_hours = '12.0'.
rs_duty-duty_hours = '8.0'.
rs_duty-month_hours = '40.0'.
ENDMETHOD.
METHOD valid_duty_passes.
DATA(ls_duty) = base_duty( ).
TRY.
mo_cut->check( ls_duty ).
CATCH {{p}}cx_licence_invalid
{{p}}cx_rating_missing
{{p}}cx_rest_too_short
{{p}}cx_duty_too_long
{{p}}cx_month_limit.
cl_abap_unit_assert=>fail( msg = 'valid duty was rejected' ).
ENDTRY.
ENDMETHOD.
METHOD licence_invalid.
DATA(ls_duty) = base_duty( ).
ls_duty-licence_valid = abap_false.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'invalid licence was accepted' ).
CATCH {{p}}cx_licence_invalid.
ENDTRY.
ENDMETHOD.
METHOD rating_missing.
DATA(ls_duty) = base_duty( ).
ls_duty-type_rating = 'B737'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'missing rating was accepted' ).
CATCH {{p}}cx_rating_missing INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = 'A320'
act = lo_exc->mv_required ).
cl_abap_unit_assert=>assert_equals( exp = 'B737'
act = lo_exc->mv_held ).
ENDTRY.
ENDMETHOD.
METHOD rest_too_short.
DATA(ls_duty) = base_duty( ).
ls_duty-rest_hours = '9.9'.
DATA lv_expected TYPE ty_hours.
lv_expected = '9.9'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'short rest was accepted' ).
CATCH {{p}}cx_rest_too_short INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = lv_expected
act = lo_exc->mv_rest_hours ).
ENDTRY.
ENDMETHOD.
METHOD duty_too_long.
DATA(ls_duty) = base_duty( ).
ls_duty-duty_hours = '13.1'.
DATA lv_expected TYPE ty_hours.
lv_expected = '13.1'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'long duty was accepted' ).
CATCH {{p}}cx_duty_too_long INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = lv_expected
act = lo_exc->mv_duty_hours ).
ENDTRY.
ENDMETHOD.
METHOD month_limit.
DATA(ls_duty) = base_duty( ).
ls_duty-month_hours = '95.0'.
DATA lv_expected TYPE ty_hours.
lv_expected = '103.0'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'month limit was ignored' ).
CATCH {{p}}cx_month_limit INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = lv_expected
act = lo_exc->mv_total_hours ).
ENDTRY.
ENDMETHOD.
METHOD first_rule_wins.
DATA(ls_duty) = base_duty( ).
ls_duty-licence_valid = abap_false.
ls_duty-type_rating = 'B737'.
ls_duty-rest_hours = '2.0'.
ls_duty-duty_hours = '20.0'.
ls_duty-month_hours = '99.0'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'no rule matched' ).
CATCH {{p}}cx_licence_invalid.
ENDTRY.
ENDMETHOD.
METHOD rating_before_rest.
DATA(ls_duty) = base_duty( ).
ls_duty-type_rating = 'B737'.
ls_duty-rest_hours = '2.0'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'no rule matched' ).
CATCH {{p}}cx_rating_missing.
ENDTRY.
ENDMETHOD.
METHOD boundary_values.
DATA(ls_duty) = base_duty( ).
ls_duty-rest_hours = '10.0'.
ls_duty-duty_hours = '13.0'.
ls_duty-month_hours = '87.0'.
TRY.
mo_cut->check( ls_duty ).
CATCH {{p}}cx_licence_invalid
{{p}}cx_rating_missing
{{p}}cx_rest_too_short
{{p}}cx_duty_too_long
{{p}}cx_month_limit.
cl_abap_unit_assert=>fail( msg = 'boundary values were rejected' ).
ENDTRY.
ENDMETHOD.
METHOD month_limit_exact.
DATA(ls_duty) = base_duty( ).
ls_duty-duty_hours = '10.0'.
ls_duty-month_hours = '90.0'.
TRY.
mo_cut->check( ls_duty ).
CATCH {{p}}cx_licence_invalid
{{p}}cx_rating_missing
{{p}}cx_rest_too_short
{{p}}cx_duty_too_long
{{p}}cx_month_limit.
cl_abap_unit_assert=>fail( msg = 'exact monthly limit was rejected' ).
ENDTRY.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,71 @@
{
"task": "T30",
"mutants": [
{
"object": "{{P}}CREW_DUTY_CHECK",
"mutant": "line 38: <> -> = (rel)",
"status": "killed",
"hidden": "10/10",
"failed_tests": [
"VALID_DUTY_PASSES",
"LICENCE_INVALID",
"RATING_MISSING",
"REST_TOO_SHORT",
"DUTY_TOO_LONG",
"MONTH_LIMIT",
"FIRST_RULE_WINS",
"RATING_BEFORE_REST",
"BOUNDARY_VALUES",
"MONTH_LIMIT_EXACT"
]
},
{
"object": "{{P}}CREW_DUTY_CHECK",
"mutant": "line 42: <> -> = (rel)",
"status": "killed",
"hidden": "8/10",
"failed_tests": [
"VALID_DUTY_PASSES",
"RATING_MISSING",
"REST_TOO_SHORT",
"DUTY_TOO_LONG",
"MONTH_LIMIT",
"RATING_BEFORE_REST",
"BOUNDARY_VALUES",
"MONTH_LIMIT_EXACT"
]
},
{
"object": "{{P}}CREW_DUTY_CHECK",
"mutant": "line 49: < -> <= (rel)",
"status": "killed",
"hidden": "1/10",
"failed_tests": [
"BOUNDARY_VALUES"
]
},
{
"object": "{{P}}CREW_DUTY_CHECK",
"mutant": "line 55: > -> >= (rel)",
"status": "killed",
"hidden": "1/10",
"failed_tests": [
"BOUNDARY_VALUES"
]
},
{
"object": "{{P}}CREW_DUTY_CHECK",
"mutant": "line 63: > -> >= (rel)",
"status": "killed",
"hidden": "2/10",
"failed_tests": [
"BOUNDARY_VALUES",
"MONTH_LIMIT_EXACT"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,69 @@
CLASS {{p}}crew_duty_check DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_hours TYPE p LENGTH 4 DECIMALS 1.
TYPES:
BEGIN OF ty_duty,
crew_id TYPE c LENGTH 10,
licence_valid TYPE abap_bool,
type_rating TYPE c LENGTH 4,
aircraft_type TYPE c LENGTH 4,
rest_hours TYPE ty_hours,
duty_hours TYPE ty_hours,
month_hours TYPE ty_hours,
END OF ty_duty.
METHODS check
IMPORTING is_duty TYPE ty_duty
RAISING
{{p}}cx_licence_invalid
{{p}}cx_rating_missing
{{p}}cx_rest_too_short
{{p}}cx_duty_too_long
{{p}}cx_month_limit.
PRIVATE SECTION.
CONSTANTS:
c_min_rest_hours TYPE ty_hours VALUE '10.0',
c_max_duty_hours TYPE ty_hours VALUE '13.0',
c_max_month_hours TYPE ty_hours VALUE '100.0'.
ENDCLASS.
CLASS {{p}}crew_duty_check IMPLEMENTATION.
METHOD check.
IF is_duty-licence_valid <> abap_true.
RAISE EXCEPTION TYPE {{p}}cx_licence_invalid.
ENDIF.
IF is_duty-type_rating <> is_duty-aircraft_type.
RAISE EXCEPTION TYPE {{p}}cx_rating_missing
EXPORTING
iv_required = is_duty-aircraft_type
iv_held = is_duty-type_rating.
ENDIF.
IF is_duty-rest_hours < c_min_rest_hours.
RAISE EXCEPTION TYPE {{p}}cx_rest_too_short
EXPORTING
iv_rest_hours = is_duty-rest_hours.
ENDIF.
IF is_duty-duty_hours > c_max_duty_hours.
RAISE EXCEPTION TYPE {{p}}cx_duty_too_long
EXPORTING
iv_duty_hours = is_duty-duty_hours.
ENDIF.
DATA lv_total_hours TYPE ty_hours.
lv_total_hours = is_duty-month_hours + is_duty-duty_hours.
IF lv_total_hours > c_max_month_hours.
RAISE EXCEPTION TYPE {{p}}cx_month_limit
EXPORTING
iv_total_hours = lv_total_hours.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,151 @@
CLASS ltc_crew_duty_check DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
TYPES ty_hours TYPE p LENGTH 4 DECIMALS 1.
DATA mo_cut TYPE REF TO {{p}}crew_duty_check.
METHODS setup.
METHODS base_duty
RETURNING VALUE(rs_duty) TYPE {{p}}crew_duty_check=>ty_duty.
METHODS valid_duty_is_ok FOR TESTING.
METHODS invalid_licence FOR TESTING.
METHODS missing_rating FOR TESTING.
METHODS rest_below_minimum FOR TESTING.
METHODS rest_at_minimum FOR TESTING.
METHODS duty_above_maximum FOR TESTING.
METHODS duty_at_maximum FOR TESTING.
METHODS month_limit_exceeded FOR TESTING.
METHODS month_limit_exact FOR TESTING.
ENDCLASS.
CLASS ltc_crew_duty_check IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}crew_duty_check( ).
ENDMETHOD.
METHOD base_duty.
CLEAR rs_duty.
rs_duty-crew_id = 'C0001'.
rs_duty-licence_valid = abap_true.
rs_duty-type_rating = 'A320'.
rs_duty-aircraft_type = 'A320'.
rs_duty-rest_hours = '12.0'.
rs_duty-duty_hours = '8.0'.
rs_duty-month_hours = '40.0'.
ENDMETHOD.
METHOD valid_duty_is_ok.
DATA(ls_duty) = base_duty( ).
TRY.
mo_cut->check( ls_duty ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'valid duty was rejected' ).
ENDTRY.
ENDMETHOD.
METHOD invalid_licence.
DATA(ls_duty) = base_duty( ).
ls_duty-licence_valid = abap_false.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'invalid licence was accepted' ).
CATCH {{p}}cx_licence_invalid.
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'wrong exception type' ).
ENDTRY.
ENDMETHOD.
METHOD missing_rating.
DATA(ls_duty) = base_duty( ).
ls_duty-type_rating = 'B737'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'missing rating was accepted' ).
CATCH {{p}}cx_rating_missing INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = 'A320'
act = lo_exc->mv_required ).
cl_abap_unit_assert=>assert_equals( exp = 'B737'
act = lo_exc->mv_held ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'wrong exception type' ).
ENDTRY.
ENDMETHOD.
METHOD rest_below_minimum.
DATA(ls_duty) = base_duty( ).
ls_duty-rest_hours = '9.9'.
DATA lv_expected TYPE ty_hours.
lv_expected = '9.9'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'short rest was accepted' ).
CATCH {{p}}cx_rest_too_short INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = lv_expected
act = lo_exc->mv_rest_hours ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'wrong exception type' ).
ENDTRY.
ENDMETHOD.
METHOD rest_at_minimum.
DATA(ls_duty) = base_duty( ).
ls_duty-rest_hours = '10.0'.
TRY.
mo_cut->check( ls_duty ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'minimum rest was rejected' ).
ENDTRY.
ENDMETHOD.
METHOD duty_above_maximum.
DATA(ls_duty) = base_duty( ).
ls_duty-duty_hours = '13.1'.
DATA lv_expected TYPE ty_hours.
lv_expected = '13.1'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'long duty was accepted' ).
CATCH {{p}}cx_duty_too_long INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = lv_expected
act = lo_exc->mv_duty_hours ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'wrong exception type' ).
ENDTRY.
ENDMETHOD.
METHOD duty_at_maximum.
DATA(ls_duty) = base_duty( ).
ls_duty-duty_hours = '13.0'.
TRY.
mo_cut->check( ls_duty ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'maximum duty was rejected' ).
ENDTRY.
ENDMETHOD.
METHOD month_limit_exceeded.
DATA(ls_duty) = base_duty( ).
ls_duty-month_hours = '95.0'.
DATA lv_expected TYPE ty_hours.
lv_expected = '103.0'.
TRY.
mo_cut->check( ls_duty ).
cl_abap_unit_assert=>fail( msg = 'month limit was ignored' ).
CATCH {{p}}cx_month_limit INTO DATA(lo_exc).
cl_abap_unit_assert=>assert_equals( exp = lv_expected
act = lo_exc->mv_total_hours ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'wrong exception type' ).
ENDTRY.
ENDMETHOD.
METHOD month_limit_exact.
DATA(ls_duty) = base_duty( ).
ls_duty-duty_hours = '8.0'.
ls_duty-month_hours = '92.0'.
TRY.
mo_cut->check( ls_duty ).
CATCH cx_root.
cl_abap_unit_assert=>fail( msg = 'exact monthly limit was rejected' ).
ENDTRY.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,23 @@
CLASS {{p}}cx_duty_too_long DEFINITION
PUBLIC
INHERITING FROM cx_static_check
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_hours TYPE p LENGTH 4 DECIMALS 1.
DATA mv_duty_hours TYPE ty_hours READ-ONLY.
METHODS constructor
IMPORTING
iv_duty_hours TYPE ty_hours.
ENDCLASS.
CLASS {{p}}cx_duty_too_long IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mv_duty_hours = iv_duty_hours.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,12 @@
CLASS {{p}}cx_licence_invalid DEFINITION
PUBLIC
INHERITING FROM cx_static_check
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
ENDCLASS.
CLASS {{p}}cx_licence_invalid IMPLEMENTATION.
ENDCLASS.

View File

@@ -0,0 +1,23 @@
CLASS {{p}}cx_month_limit DEFINITION
PUBLIC
INHERITING FROM cx_static_check
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_hours TYPE p LENGTH 4 DECIMALS 1.
DATA mv_total_hours TYPE ty_hours READ-ONLY.
METHODS constructor
IMPORTING
iv_total_hours TYPE ty_hours.
ENDCLASS.
CLASS {{p}}cx_month_limit IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mv_total_hours = iv_total_hours.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,26 @@
CLASS {{p}}cx_rating_missing DEFINITION
PUBLIC
INHERITING FROM cx_static_check
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_rating TYPE c LENGTH 4.
DATA mv_required TYPE ty_rating READ-ONLY.
DATA mv_held TYPE ty_rating READ-ONLY.
METHODS constructor
IMPORTING
iv_required TYPE ty_rating
iv_held TYPE ty_rating.
ENDCLASS.
CLASS {{p}}cx_rating_missing IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mv_required = iv_required.
mv_held = iv_held.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,23 @@
CLASS {{p}}cx_rest_too_short DEFINITION
PUBLIC
INHERITING FROM cx_static_check
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_hours TYPE p LENGTH 4 DECIMALS 1.
DATA mv_rest_hours TYPE ty_hours READ-ONLY.
METHODS constructor
IMPORTING
iv_rest_hours TYPE ty_hours.
ENDCLASS.
CLASS {{p}}cx_rest_too_short IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mv_rest_hours = iv_rest_hours.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,100 @@
# 1. Goal
A rostering system assigns pilots to flight duties. Before the system confirms an
assignment, it calls one check. The check rejects the assignment with a reason if
the pilot may not fly the duty. The system needs one exception for each reason.
# 2. Open questions
None.
# 3. Context
- All objects are in package $TMP.
- The check uses only the data that the caller passes. It does not read a database.
- The caller fills the structure TY_DUTY and calls the method CHECK.
# 4. Contract
## 4.1 Class {{P}}CREW_DUTY_CHECK
- Package $TMP. The class is public, final and create public.
- The class can be created without parameters.
- Public type TY_HOURS: packed number, length 4, 1 decimal place.
- Public type TY_DUTY, a structure with these components:
| Component | Type |
| --- | --- |
| CREW_ID | c LENGTH 10 |
| LICENCE_VALID | abap_bool |
| TYPE_RATING | c LENGTH 4 |
| AIRCRAFT_TYPE | c LENGTH 4 |
| REST_HOURS | ty_hours |
| DUTY_HOURS | ty_hours |
| MONTH_HOURS | ty_hours |
- Public method CHECK:
- IMPORTING is_duty TYPE ty_duty
- RAISING {{P}}CX_LICENCE_INVALID, {{P}}CX_RATING_MISSING,
{{P}}CX_REST_TOO_SHORT, {{P}}CX_DUTY_TOO_LONG, {{P}}CX_MONTH_LIMIT
- The method has no return value.
## 4.2 Exception classes
Create these five classes in package $TMP. Each class is public, final, create public
and inherits from CX_STATIC_CHECK.
{{P}}CX_LICENCE_INVALID
- No own components.
{{P}}CX_RATING_MISSING
- Public type TY_RATING: character, length 4.
- Public read-only attributes MV_REQUIRED and MV_HELD, type TY_RATING.
- Public constructor with importing parameters IV_REQUIRED and IV_HELD, type TY_RATING.
The constructor copies IV_REQUIRED to MV_REQUIRED and IV_HELD to MV_HELD.
{{P}}CX_REST_TOO_SHORT
- Public type TY_HOURS: packed number, length 4, 1 decimal place.
- Public read-only attribute MV_REST_HOURS, type TY_HOURS.
- Public constructor with importing parameter IV_REST_HOURS, type TY_HOURS.
The constructor copies IV_REST_HOURS to MV_REST_HOURS.
{{P}}CX_DUTY_TOO_LONG
- Public type TY_HOURS: packed number, length 4, 1 decimal place.
- Public read-only attribute MV_DUTY_HOURS, type TY_HOURS.
- Public constructor with importing parameter IV_DUTY_HOURS, type TY_HOURS.
The constructor copies IV_DUTY_HOURS to MV_DUTY_HOURS.
{{P}}CX_MONTH_LIMIT
- Public type TY_HOURS: packed number, length 4, 1 decimal place.
- Public read-only attribute MV_TOTAL_HOURS, type TY_HOURS.
- Public constructor with importing parameter IV_TOTAL_HOURS, type TY_HOURS.
The constructor copies IV_TOTAL_HOURS to MV_TOTAL_HOURS.
# 5. Business rules
The method CHECK applies these rules in this sequence. It raises the exception of the
first rule that fails and stops. If no rule fails, the method returns to the caller.
1. Licence. If is_duty-licence_valid is not abap_true, raise {{P}}CX_LICENCE_INVALID.
2. Type rating. If is_duty-type_rating is not equal to is_duty-aircraft_type, raise
{{P}}CX_RATING_MISSING. Pass is_duty-aircraft_type as IV_REQUIRED and
is_duty-type_rating as IV_HELD.
3. Rest. If is_duty-rest_hours is less than 10.0, raise {{P}}CX_REST_TOO_SHORT.
Pass is_duty-rest_hours as IV_REST_HOURS.
4. Duty period. If is_duty-duty_hours is greater than 13.0, raise
{{P}}CX_DUTY_TOO_LONG. Pass is_duty-duty_hours as IV_DUTY_HOURS.
5. Monthly hours. Add is_duty-month_hours and is_duty-duty_hours. If the sum is
greater than 100.0, raise {{P}}CX_MONTH_LIMIT. Pass the sum as IV_TOTAL_HOURS.
# 6. Constraints
- Release target: SAP_BASIS 8.16.
- Coding standards: Clean ABAP. Methods below 40 statements. No global variables.
No comment that restates the code.
- Out of scope: database tables, message classes, reports, function modules, dynpros.
# 7. Acceptance
- The six classes are active and have no syntax error.
- The hidden tests pass.
- Write your own ABAP Unit tests for the class {{P}}CREW_DUTY_CHECK.

View File

@@ -0,0 +1,97 @@
{
"id": "G0128",
"category": "D",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [],
"contract": [
{
"type": "CLAS",
"name": "{{P}}CREW_DUTY_CHECK"
},
{
"type": "CLAS",
"name": "{{P}}CX_LICENCE_INVALID"
},
{
"type": "CLAS",
"name": "{{P}}CX_RATING_MISSING"
},
{
"type": "CLAS",
"name": "{{P}}CX_REST_TOO_SHORT"
},
{
"type": "CLAS",
"name": "{{P}}CX_DUTY_TOO_LONG"
},
{
"type": "CLAS",
"name": "{{P}}CX_MONTH_LIMIT"
}
],
"out_of_scope": [
"Database tables",
"Message classes",
"Reports",
"Function modules",
"Dynpros"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}CREW_CHECK_HIDDEN",
"file": "hidden/crew_check_hidden.clas.abap",
"description": "Hidden tests for the crew duty check and its exception classes"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}CX_LICENCE_INVALID",
"file": "reference/cx_licence_invalid.clas.abap",
"description": "Exception: licence is not valid"
},
{
"type": "CLAS",
"name": "{{P}}CX_RATING_MISSING",
"file": "reference/cx_rating_missing.clas.abap",
"description": "Exception: type rating does not match the aircraft type"
},
{
"type": "CLAS",
"name": "{{P}}CX_REST_TOO_SHORT",
"file": "reference/cx_rest_too_short.clas.abap",
"description": "Exception: rest period is too short"
},
{
"type": "CLAS",
"name": "{{P}}CX_DUTY_TOO_LONG",
"file": "reference/cx_duty_too_long.clas.abap",
"description": "Exception: flight duty period is too long"
},
{
"type": "CLAS",
"name": "{{P}}CX_MONTH_LIMIT",
"file": "reference/cx_month_limit.clas.abap",
"description": "Exception: monthly hour limit is exceeded"
},
{
"type": "CLAS",
"name": "{{P}}CREW_DUTY_CHECK",
"file": "reference/crew_duty_check.clas.abap",
"description": "Crew duty check",
"testclasses_file": "reference/crew_duty_check.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"cyclomatic_complexity"
]
}