Object type mix: INTF, TABL, STRU, MSAG, exception tasks (harness G2, mutants, generator notes), balanced generator, kind-deficit job order, dashboard mix card

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-05 18:52:29 +02:00
parent 454db6626c
commit b119f1afac
39 changed files with 2329 additions and 24 deletions

View File

@@ -0,0 +1,51 @@
INTERFACE {{p}}if_parcel_fee PUBLIC.
TYPES ty_weight_g TYPE i.
TYPES ty_cents TYPE i.
TYPES ty_zone TYPE c LENGTH 1.
TYPES ty_reason TYPE c LENGTH 9.
CONSTANTS:
BEGIN OF c_zone,
home TYPE ty_zone VALUE '1',
national TYPE ty_zone VALUE '2',
europe TYPE ty_zone VALUE '3',
END OF c_zone.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'OK',
weight TYPE ty_reason VALUE 'WEIGHT',
zone TYPE ty_reason VALUE 'ZONE',
END OF c_reason.
CONSTANTS:
BEGIN OF c_limit,
min_weight TYPE ty_weight_g VALUE 1,
max_weight TYPE ty_weight_g VALUE 31500,
END OF c_limit.
CONSTANTS:
BEGIN OF c_surcharge,
per_step TYPE ty_cents VALUE 90,
express TYPE ty_cents VALUE 750,
END OF c_surcharge.
METHODS check_input
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
RETURNING VALUE(rv_reason) TYPE ty_reason.
METHODS base_fee
IMPORTING iv_zone TYPE ty_zone
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS weight_surcharge
IMPORTING iv_weight_g TYPE ty_weight_g
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS total_fee
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
iv_express TYPE abap_bool
RETURNING VALUE(rv_cents) TYPE ty_cents.
ENDINTERFACE.

View File

@@ -0,0 +1,51 @@
INTERFACE {{p}}if_parcel_fee PUBLIC.
TYPES ty_weight_g TYPE i.
TYPES ty_cents TYPE i.
TYPES ty_zone TYPE c LENGTH 1.
TYPES ty_reason TYPE c LENGTH 10.
CONSTANTS:
BEGIN OF c_zone,
home TYPE ty_zone VALUE 'Z',
national TYPE ty_zone VALUE '2',
europe TYPE ty_zone VALUE '3',
END OF c_zone.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'OK',
weight TYPE ty_reason VALUE 'WEIGHT',
zone TYPE ty_reason VALUE 'ZONE',
END OF c_reason.
CONSTANTS:
BEGIN OF c_limit,
min_weight TYPE ty_weight_g VALUE 1,
max_weight TYPE ty_weight_g VALUE 31500,
END OF c_limit.
CONSTANTS:
BEGIN OF c_surcharge,
per_step TYPE ty_cents VALUE 90,
express TYPE ty_cents VALUE 750,
END OF c_surcharge.
METHODS check_input
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
RETURNING VALUE(rv_reason) TYPE ty_reason.
METHODS base_fee
IMPORTING iv_zone TYPE ty_zone
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS weight_surcharge
IMPORTING iv_weight_g TYPE ty_weight_g
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS total_fee
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
iv_express TYPE abap_bool
RETURNING VALUE(rv_cents) TYPE ty_cents.
ENDINTERFACE.

View File

@@ -0,0 +1,51 @@
INTERFACE {{p}}if_parcel_fee PUBLIC.
TYPES ty_weight_g TYPE i.
TYPES ty_cents TYPE i.
TYPES ty_zone TYPE c LENGTH 1.
TYPES ty_reason TYPE c LENGTH 10.
CONSTANTS:
BEGIN OF c_zone,
home TYPE ty_zone VALUE '1',
national TYPE ty_zone VALUE '2',
europe TYPE ty_zone VALUE 'Z',
END OF c_zone.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'OK',
weight TYPE ty_reason VALUE 'WEIGHT',
zone TYPE ty_reason VALUE 'ZONE',
END OF c_reason.
CONSTANTS:
BEGIN OF c_limit,
min_weight TYPE ty_weight_g VALUE 1,
max_weight TYPE ty_weight_g VALUE 31500,
END OF c_limit.
CONSTANTS:
BEGIN OF c_surcharge,
per_step TYPE ty_cents VALUE 90,
express TYPE ty_cents VALUE 750,
END OF c_surcharge.
METHODS check_input
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
RETURNING VALUE(rv_reason) TYPE ty_reason.
METHODS base_fee
IMPORTING iv_zone TYPE ty_zone
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS weight_surcharge
IMPORTING iv_weight_g TYPE ty_weight_g
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS total_fee
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
iv_express TYPE abap_bool
RETURNING VALUE(rv_cents) TYPE ty_cents.
ENDINTERFACE.

View File

@@ -0,0 +1,51 @@
INTERFACE {{p}}if_parcel_fee PUBLIC.
TYPES ty_weight_g TYPE i.
TYPES ty_cents TYPE i.
TYPES ty_zone TYPE c LENGTH 1.
TYPES ty_reason TYPE c LENGTH 10.
CONSTANTS:
BEGIN OF c_zone,
home TYPE ty_zone VALUE '1',
national TYPE ty_zone VALUE '2',
europe TYPE ty_zone VALUE '3',
END OF c_zone.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'ZK',
weight TYPE ty_reason VALUE 'WEIGHT',
zone TYPE ty_reason VALUE 'ZONE',
END OF c_reason.
CONSTANTS:
BEGIN OF c_limit,
min_weight TYPE ty_weight_g VALUE 1,
max_weight TYPE ty_weight_g VALUE 31500,
END OF c_limit.
CONSTANTS:
BEGIN OF c_surcharge,
per_step TYPE ty_cents VALUE 90,
express TYPE ty_cents VALUE 750,
END OF c_surcharge.
METHODS check_input
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
RETURNING VALUE(rv_reason) TYPE ty_reason.
METHODS base_fee
IMPORTING iv_zone TYPE ty_zone
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS weight_surcharge
IMPORTING iv_weight_g TYPE ty_weight_g
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS total_fee
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
iv_express TYPE abap_bool
RETURNING VALUE(rv_cents) TYPE ty_cents.
ENDINTERFACE.

View File

@@ -0,0 +1,51 @@
INTERFACE {{p}}if_parcel_fee PUBLIC.
TYPES ty_weight_g TYPE i.
TYPES ty_cents TYPE i.
TYPES ty_zone TYPE c LENGTH 1.
TYPES ty_reason TYPE c LENGTH 10.
CONSTANTS:
BEGIN OF c_zone,
home TYPE ty_zone VALUE '1',
national TYPE ty_zone VALUE '2',
europe TYPE ty_zone VALUE '3',
END OF c_zone.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'OK',
weight TYPE ty_reason VALUE 'WEIGHT',
zone TYPE ty_reason VALUE 'YONE',
END OF c_reason.
CONSTANTS:
BEGIN OF c_limit,
min_weight TYPE ty_weight_g VALUE 1,
max_weight TYPE ty_weight_g VALUE 31500,
END OF c_limit.
CONSTANTS:
BEGIN OF c_surcharge,
per_step TYPE ty_cents VALUE 90,
express TYPE ty_cents VALUE 750,
END OF c_surcharge.
METHODS check_input
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
RETURNING VALUE(rv_reason) TYPE ty_reason.
METHODS base_fee
IMPORTING iv_zone TYPE ty_zone
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS weight_surcharge
IMPORTING iv_weight_g TYPE ty_weight_g
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS total_fee
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
iv_express TYPE abap_bool
RETURNING VALUE(rv_cents) TYPE ty_cents.
ENDINTERFACE.

View File

@@ -0,0 +1,29 @@
{
"id": "G1900",
"pool": "train",
"object_type": "INTF",
"category": "A",
"attempts": [
{
"stage": "validate",
"oracle": 0,
"null": 0
},
{
"stage": "validate",
"oracle": 80.6,
"null": 0
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 5,
"killed": 5,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,159 @@
CLASS {{p}}parcel_fee_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PUBLIC SECTION.
INTERFACES {{p}}if_parcel_fee.
PRIVATE SECTION.
METHODS zone_values FOR TESTING.
METHODS reason_values FOR TESTING.
METHODS limit_values FOR TESTING.
METHODS surcharge_values FOR TESTING.
METHODS type_lengths FOR TESTING.
METHODS check_input_sig FOR TESTING.
METHODS base_fee_sig FOR TESTING.
METHODS weight_surcharge_sig FOR TESTING.
METHODS total_fee_sig FOR TESTING.
ENDCLASS.
CLASS {{p}}parcel_fee_hidden IMPLEMENTATION.
METHOD {{p}}if_parcel_fee~check_input.
IF iv_weight_g < {{p}}if_parcel_fee=>c_limit-min_weight
OR iv_weight_g > {{p}}if_parcel_fee=>c_limit-max_weight.
rv_reason = {{p}}if_parcel_fee=>c_reason-weight.
ELSEIF iv_zone <> {{p}}if_parcel_fee=>c_zone-home
AND iv_zone <> {{p}}if_parcel_fee=>c_zone-national
AND iv_zone <> {{p}}if_parcel_fee=>c_zone-europe.
rv_reason = {{p}}if_parcel_fee=>c_reason-zone.
ELSE.
rv_reason = {{p}}if_parcel_fee=>c_reason-ok.
ENDIF.
ENDMETHOD.
METHOD {{p}}if_parcel_fee~base_fee.
CASE iv_zone.
WHEN {{p}}if_parcel_fee=>c_zone-home.
rv_cents = 350.
WHEN {{p}}if_parcel_fee=>c_zone-national.
rv_cents = 620.
WHEN {{p}}if_parcel_fee=>c_zone-europe.
rv_cents = 990.
WHEN OTHERS.
rv_cents = 0.
ENDCASE.
ENDMETHOD.
METHOD {{p}}if_parcel_fee~weight_surcharge.
IF iv_weight_g > 1000.
rv_cents = ( iv_weight_g - 1000 + 999 ) DIV 1000
* {{p}}if_parcel_fee=>c_surcharge-per_step.
ENDIF.
ENDMETHOD.
METHOD {{p}}if_parcel_fee~total_fee.
IF me->{{p}}if_parcel_fee~check_input( iv_weight_g = iv_weight_g
iv_zone = iv_zone )
<> {{p}}if_parcel_fee=>c_reason-ok.
RETURN.
ENDIF.
rv_cents = me->{{p}}if_parcel_fee~base_fee( iv_zone )
+ me->{{p}}if_parcel_fee~weight_surcharge( iv_weight_g ).
IF iv_express = abap_true.
rv_cents = rv_cents + {{p}}if_parcel_fee=>c_surcharge-express.
ENDIF.
ENDMETHOD.
METHOD zone_values.
cl_abap_unit_assert=>assert_equals( exp = '1' act = {{p}}if_parcel_fee=>c_zone-home ).
cl_abap_unit_assert=>assert_equals( exp = '2' act = {{p}}if_parcel_fee=>c_zone-national ).
cl_abap_unit_assert=>assert_equals( exp = '3' act = {{p}}if_parcel_fee=>c_zone-europe ).
ENDMETHOD.
METHOD reason_values.
cl_abap_unit_assert=>assert_equals( exp = 'OK' act = {{p}}if_parcel_fee=>c_reason-ok ).
cl_abap_unit_assert=>assert_equals( exp = 'WEIGHT' act = {{p}}if_parcel_fee=>c_reason-weight ).
cl_abap_unit_assert=>assert_equals( exp = 'ZONE' act = {{p}}if_parcel_fee=>c_reason-zone ).
ENDMETHOD.
METHOD limit_values.
cl_abap_unit_assert=>assert_equals( exp = 1 act = {{p}}if_parcel_fee=>c_limit-min_weight ).
cl_abap_unit_assert=>assert_equals( exp = 31500 act = {{p}}if_parcel_fee=>c_limit-max_weight ).
ENDMETHOD.
METHOD surcharge_values.
cl_abap_unit_assert=>assert_equals( exp = 90 act = {{p}}if_parcel_fee=>c_surcharge-per_step ).
cl_abap_unit_assert=>assert_equals( exp = 750 act = {{p}}if_parcel_fee=>c_surcharge-express ).
ENDMETHOD.
METHOD type_lengths.
DATA lv_zone TYPE {{p}}if_parcel_fee=>ty_zone.
DATA lv_reason TYPE {{p}}if_parcel_fee=>ty_reason.
DATA lv_weight TYPE {{p}}if_parcel_fee=>ty_weight_g.
DATA lv_cents TYPE {{p}}if_parcel_fee=>ty_cents.
DATA(lv_char1) = 'A'.
DATA(lv_char10) = 'ABCDEFGHIJ'.
DATA(lo_zone) = cl_abap_typedescr=>describe_by_data( lv_zone ).
DATA(lo_reason) = cl_abap_typedescr=>describe_by_data( lv_reason ).
DATA(lo_weight) = cl_abap_typedescr=>describe_by_data( lv_weight ).
DATA(lo_cents) = cl_abap_typedescr=>describe_by_data( lv_cents ).
DATA(lo_char1) = cl_abap_typedescr=>describe_by_data( lv_char1 ).
DATA(lo_char10) = cl_abap_typedescr=>describe_by_data( lv_char10 ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_char
act = lo_zone->type_kind ).
cl_abap_unit_assert=>assert_equals( exp = lo_char1->length act = lo_zone->length ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_char
act = lo_reason->type_kind ).
cl_abap_unit_assert=>assert_equals( exp = lo_char10->length act = lo_reason->length ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_int
act = lo_weight->type_kind ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_int
act = lo_cents->type_kind ).
ENDMETHOD.
METHOD check_input_sig.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals(
exp = {{p}}if_parcel_fee=>c_reason-ok
act = lo_cut->check_input( iv_weight_g = 500 iv_zone = {{p}}if_parcel_fee=>c_zone-home ) ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}if_parcel_fee=>c_reason-weight
act = lo_cut->check_input( iv_weight_g = 0 iv_zone = {{p}}if_parcel_fee=>c_zone-home ) ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}if_parcel_fee=>c_reason-zone
act = lo_cut->check_input( iv_weight_g = 500 iv_zone = '9' ) ).
ENDMETHOD.
METHOD base_fee_sig.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = 350
act = lo_cut->base_fee( iv_zone = {{p}}if_parcel_fee=>c_zone-home ) ).
cl_abap_unit_assert=>assert_equals( exp = 620
act = lo_cut->base_fee( iv_zone = {{p}}if_parcel_fee=>c_zone-national ) ).
cl_abap_unit_assert=>assert_equals( exp = 990
act = lo_cut->base_fee( iv_zone = {{p}}if_parcel_fee=>c_zone-europe ) ).
ENDMETHOD.
METHOD weight_surcharge_sig.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = 0
act = lo_cut->weight_surcharge( iv_weight_g = 1000 ) ).
cl_abap_unit_assert=>assert_equals( exp = 90
act = lo_cut->weight_surcharge( iv_weight_g = 1001 ) ).
cl_abap_unit_assert=>assert_equals( exp = 180
act = lo_cut->weight_surcharge( iv_weight_g = 2001 ) ).
ENDMETHOD.
METHOD total_fee_sig.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = 530
act = lo_cut->total_fee( iv_weight_g = 2500 iv_zone = '1' iv_express = abap_false ) ).
cl_abap_unit_assert=>assert_equals( exp = 1280
act = lo_cut->total_fee( iv_weight_g = 2500 iv_zone = '1' iv_express = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 0
act = lo_cut->total_fee( iv_weight_g = 0 iv_zone = '1' iv_express = abap_false ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,55 @@
{
"task": "G1900",
"mutants": [
{
"object": "{{P}}IF_PARCEL_FEE",
"mutant": "line 5: LENGTH 10 -> LENGTH 9 (length)",
"status": "killed",
"hidden": "8/9",
"failed_tests": [
"TYPE_LENGTHS"
]
},
{
"object": "{{P}}IF_PARCEL_FEE",
"mutant": "line 9: VALUE '1' -> VALUE 'Z' (lit)",
"status": "killed",
"hidden": "7/9",
"failed_tests": [
"TOTAL_FEE_SIG",
"ZONE_VALUES"
]
},
{
"object": "{{P}}IF_PARCEL_FEE",
"mutant": "line 11: VALUE '3' -> VALUE 'Z' (lit)",
"status": "killed",
"hidden": "8/9",
"failed_tests": [
"ZONE_VALUES"
]
},
{
"object": "{{P}}IF_PARCEL_FEE",
"mutant": "line 16: VALUE 'OK' -> VALUE 'ZK' (lit)",
"status": "killed",
"hidden": "8/9",
"failed_tests": [
"REASON_VALUES"
]
},
{
"object": "{{P}}IF_PARCEL_FEE",
"mutant": "line 18: VALUE 'ZONE' -> VALUE 'YONE' (lit)",
"status": "killed",
"hidden": "8/9",
"failed_tests": [
"REASON_VALUES"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,51 @@
INTERFACE {{p}}if_parcel_fee PUBLIC.
TYPES ty_weight_g TYPE i.
TYPES ty_cents TYPE i.
TYPES ty_zone TYPE c LENGTH 1.
TYPES ty_reason TYPE c LENGTH 10.
CONSTANTS:
BEGIN OF c_zone,
home TYPE ty_zone VALUE '1',
national TYPE ty_zone VALUE '2',
europe TYPE ty_zone VALUE '3',
END OF c_zone.
CONSTANTS:
BEGIN OF c_reason,
ok TYPE ty_reason VALUE 'OK',
weight TYPE ty_reason VALUE 'WEIGHT',
zone TYPE ty_reason VALUE 'ZONE',
END OF c_reason.
CONSTANTS:
BEGIN OF c_limit,
min_weight TYPE ty_weight_g VALUE 1,
max_weight TYPE ty_weight_g VALUE 31500,
END OF c_limit.
CONSTANTS:
BEGIN OF c_surcharge,
per_step TYPE ty_cents VALUE 90,
express TYPE ty_cents VALUE 750,
END OF c_surcharge.
METHODS check_input
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
RETURNING VALUE(rv_reason) TYPE ty_reason.
METHODS base_fee
IMPORTING iv_zone TYPE ty_zone
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS weight_surcharge
IMPORTING iv_weight_g TYPE ty_weight_g
RETURNING VALUE(rv_cents) TYPE ty_cents.
METHODS total_fee
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
iv_express TYPE abap_bool
RETURNING VALUE(rv_cents) TYPE ty_cents.
ENDINTERFACE.

View File

@@ -0,0 +1,180 @@
CLASS {{p}}parcel_fee_test DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PUBLIC SECTION.
INTERFACES {{p}}if_parcel_fee.
PRIVATE SECTION.
METHODS zone_values FOR TESTING.
METHODS reason_values FOR TESTING.
METHODS limit_values FOR TESTING.
METHODS surcharge_values FOR TESTING.
METHODS type_lengths FOR TESTING.
METHODS valid_input FOR TESTING.
METHODS weight_out_of_range FOR TESTING.
METHODS unknown_zone FOR TESTING.
METHODS base_fee_by_zone FOR TESTING.
METHODS surcharge_steps FOR TESTING.
METHODS total_fee_with_express FOR TESTING.
METHODS total_fee_invalid FOR TESTING.
ENDCLASS.
CLASS {{p}}parcel_fee_test IMPLEMENTATION.
METHOD {{p}}if_parcel_fee~check_input.
IF iv_weight_g < {{p}}if_parcel_fee=>c_limit-min_weight
OR iv_weight_g > {{p}}if_parcel_fee=>c_limit-max_weight.
rv_reason = {{p}}if_parcel_fee=>c_reason-weight.
ELSEIF iv_zone <> {{p}}if_parcel_fee=>c_zone-home
AND iv_zone <> {{p}}if_parcel_fee=>c_zone-national
AND iv_zone <> {{p}}if_parcel_fee=>c_zone-europe.
rv_reason = {{p}}if_parcel_fee=>c_reason-zone.
ELSE.
rv_reason = {{p}}if_parcel_fee=>c_reason-ok.
ENDIF.
ENDMETHOD.
METHOD {{p}}if_parcel_fee~base_fee.
CASE iv_zone.
WHEN {{p}}if_parcel_fee=>c_zone-home.
rv_cents = 350.
WHEN {{p}}if_parcel_fee=>c_zone-national.
rv_cents = 620.
WHEN {{p}}if_parcel_fee=>c_zone-europe.
rv_cents = 990.
WHEN OTHERS.
rv_cents = 0.
ENDCASE.
ENDMETHOD.
METHOD {{p}}if_parcel_fee~weight_surcharge.
IF iv_weight_g > 1000.
rv_cents = ( iv_weight_g - 1000 + 999 ) DIV 1000
* {{p}}if_parcel_fee=>c_surcharge-per_step.
ENDIF.
ENDMETHOD.
METHOD {{p}}if_parcel_fee~total_fee.
IF me->{{p}}if_parcel_fee~check_input( iv_weight_g = iv_weight_g
iv_zone = iv_zone )
<> {{p}}if_parcel_fee=>c_reason-ok.
RETURN.
ENDIF.
rv_cents = me->{{p}}if_parcel_fee~base_fee( iv_zone )
+ me->{{p}}if_parcel_fee~weight_surcharge( iv_weight_g ).
IF iv_express = abap_true.
rv_cents = rv_cents + {{p}}if_parcel_fee=>c_surcharge-express.
ENDIF.
ENDMETHOD.
METHOD zone_values.
cl_abap_unit_assert=>assert_equals( exp = '1' act = {{p}}if_parcel_fee=>c_zone-home ).
cl_abap_unit_assert=>assert_equals( exp = '2' act = {{p}}if_parcel_fee=>c_zone-national ).
cl_abap_unit_assert=>assert_equals( exp = '3' act = {{p}}if_parcel_fee=>c_zone-europe ).
ENDMETHOD.
METHOD reason_values.
cl_abap_unit_assert=>assert_equals( exp = 'OK' act = {{p}}if_parcel_fee=>c_reason-ok ).
cl_abap_unit_assert=>assert_equals( exp = 'WEIGHT' act = {{p}}if_parcel_fee=>c_reason-weight ).
cl_abap_unit_assert=>assert_equals( exp = 'ZONE' act = {{p}}if_parcel_fee=>c_reason-zone ).
ENDMETHOD.
METHOD limit_values.
cl_abap_unit_assert=>assert_equals( exp = 1 act = {{p}}if_parcel_fee=>c_limit-min_weight ).
cl_abap_unit_assert=>assert_equals( exp = 31500 act = {{p}}if_parcel_fee=>c_limit-max_weight ).
ENDMETHOD.
METHOD surcharge_values.
cl_abap_unit_assert=>assert_equals( exp = 90 act = {{p}}if_parcel_fee=>c_surcharge-per_step ).
cl_abap_unit_assert=>assert_equals( exp = 750 act = {{p}}if_parcel_fee=>c_surcharge-express ).
ENDMETHOD.
METHOD type_lengths.
DATA lv_zone TYPE {{p}}if_parcel_fee=>ty_zone.
DATA lv_reason TYPE {{p}}if_parcel_fee=>ty_reason.
DATA lv_weight TYPE {{p}}if_parcel_fee=>ty_weight_g.
DATA lv_cents TYPE {{p}}if_parcel_fee=>ty_cents.
DATA(lv_char1) = 'A'.
DATA(lv_char10) = 'ABCDEFGHIJ'.
DATA(lo_zone) = cl_abap_typedescr=>describe_by_data( lv_zone ).
DATA(lo_reason) = cl_abap_typedescr=>describe_by_data( lv_reason ).
DATA(lo_weight) = cl_abap_typedescr=>describe_by_data( lv_weight ).
DATA(lo_cents) = cl_abap_typedescr=>describe_by_data( lv_cents ).
DATA(lo_char1) = cl_abap_typedescr=>describe_by_data( lv_char1 ).
DATA(lo_char10) = cl_abap_typedescr=>describe_by_data( lv_char10 ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_char
act = lo_zone->type_kind ).
cl_abap_unit_assert=>assert_equals( exp = lo_char1->length act = lo_zone->length ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_char
act = lo_reason->type_kind ).
cl_abap_unit_assert=>assert_equals( exp = lo_char10->length act = lo_reason->length ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_int
act = lo_weight->type_kind ).
cl_abap_unit_assert=>assert_equals( exp = cl_abap_typedescr=>typekind_int
act = lo_cents->type_kind ).
ENDMETHOD.
METHOD valid_input.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_parcel_fee=>c_reason-ok
act = lo_cut->check_input( iv_weight_g = 1 iv_zone = '1' ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_parcel_fee=>c_reason-ok
act = lo_cut->check_input( iv_weight_g = 31500 iv_zone = '3' ) ).
ENDMETHOD.
METHOD weight_out_of_range.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_parcel_fee=>c_reason-weight
act = lo_cut->check_input( iv_weight_g = 0 iv_zone = '1' ) ).
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_parcel_fee=>c_reason-weight
act = lo_cut->check_input( iv_weight_g = 31501 iv_zone = '1' ) ).
ENDMETHOD.
METHOD unknown_zone.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = {{p}}if_parcel_fee=>c_reason-zone
act = lo_cut->check_input( iv_weight_g = 500 iv_zone = '9' ) ).
ENDMETHOD.
METHOD base_fee_by_zone.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = 350 act = lo_cut->base_fee( iv_zone = '1' ) ).
cl_abap_unit_assert=>assert_equals( exp = 620 act = lo_cut->base_fee( iv_zone = '2' ) ).
cl_abap_unit_assert=>assert_equals( exp = 990 act = lo_cut->base_fee( iv_zone = '3' ) ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lo_cut->base_fee( iv_zone = '9' ) ).
ENDMETHOD.
METHOD surcharge_steps.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = 0
act = lo_cut->weight_surcharge( iv_weight_g = 1000 ) ).
cl_abap_unit_assert=>assert_equals( exp = 90
act = lo_cut->weight_surcharge( iv_weight_g = 1001 ) ).
cl_abap_unit_assert=>assert_equals( exp = 90
act = lo_cut->weight_surcharge( iv_weight_g = 2000 ) ).
cl_abap_unit_assert=>assert_equals( exp = 180
act = lo_cut->weight_surcharge( iv_weight_g = 2001 ) ).
ENDMETHOD.
METHOD total_fee_with_express.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = 530
act = lo_cut->total_fee( iv_weight_g = 2500 iv_zone = '1' iv_express = abap_false ) ).
cl_abap_unit_assert=>assert_equals( exp = 1280
act = lo_cut->total_fee( iv_weight_g = 2500 iv_zone = '1' iv_express = abap_true ) ).
ENDMETHOD.
METHOD total_fee_invalid.
DATA lo_cut TYPE REF TO {{p}}if_parcel_fee.
lo_cut = me.
cl_abap_unit_assert=>assert_equals( exp = 0
act = lo_cut->total_fee( iv_weight_g = 0 iv_zone = '1' iv_express = abap_true ) ).
cl_abap_unit_assert=>assert_equals( exp = 0
act = lo_cut->total_fee( iv_weight_g = 500 iv_zone = '9' iv_express = abap_false ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,106 @@
# 1. Goal
A logistics program calculates the shipping fee of a parcel. The program must not
contain the fee rules itself. It uses an interface as the contract. Create this
interface.
# 2. Open questions
None.
# 3. Context
- Package $TMP, client 001.
- The interface {{P}}IF_PARCEL_FEE does not exist yet. Create it.
- A parcel has a weight in grams, a shipping zone, and an express flag. A fee is
an amount in whole cents.
- The interface is only a contract. Other programs implement it and calculate the
fee. The interface declares four methods:
- check_input: checks the weight and the zone and returns a reason code.
- base_fee: returns the base fee of a zone.
- weight_surcharge: returns the surcharge that the weight causes.
- total_fee: returns the complete fee of a parcel.
- The meaning of the values: zone '1' is the home zone, zone '2' is the national
zone, zone '3' is the europe zone. The reason 'OK' means that the input is
valid, 'WEIGHT' means that the weight is out of range, and 'ZONE' means that the
zone is unknown. The base fee is 350 cents for zone '1', 620 cents for zone '2',
and 990 cents for zone '3'. The first 1000 grams are included in the base fee.
Each started 1000 grams above 1000 grams costs 90 cents. The express option
costs 750 cents. A call with invalid input returns the fee 0.
# 4. Contract
Create the interface {{P}}IF_PARCEL_FEE in package $TMP. The interface is public.
It contains exactly the types, the constants, and the methods below. Do not add
other components.
Types:
- ty_weight_g TYPE i
- ty_cents TYPE i
- ty_zone TYPE c LENGTH 1
- ty_reason TYPE c LENGTH 10
Constants:
- c_zone: components home, national, europe, each TYPE ty_zone
- c_reason: components ok, weight, zone, each TYPE ty_reason
- c_limit: components min_weight, max_weight, each TYPE ty_weight_g
- c_surcharge: components per_step, express, each TYPE ty_cents
Methods:
- check_input
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
RETURNING VALUE(rv_reason) TYPE ty_reason
- base_fee
IMPORTING iv_zone TYPE ty_zone
RETURNING VALUE(rv_cents) TYPE ty_cents
- weight_surcharge
IMPORTING iv_weight_g TYPE ty_weight_g
RETURNING VALUE(rv_cents) TYPE ty_cents
- total_fee
IMPORTING iv_weight_g TYPE ty_weight_g
iv_zone TYPE ty_zone
iv_express TYPE abap_bool
RETURNING VALUE(rv_cents) TYPE ty_cents
# 5. Business rules
1. The type ty_zone is a character type with length 1. The type ty_reason is a
character type with length 10. The types ty_weight_g and ty_cents are integer
types.
2. The constant structure c_zone has the components home, national, and europe.
Each component has the type ty_zone. The values are '1', '2', and '3'.
3. The constant structure c_reason has the components ok, weight, and zone. Each
component has the type ty_reason. The values are 'OK', 'WEIGHT', and 'ZONE'.
4. The constant structure c_limit has the components min_weight and max_weight.
Each component has the type ty_weight_g. The values are 1 and 31500.
5. The constant structure c_surcharge has the components per_step and express.
Each component has the type ty_cents. The values are 90 and 750.
6. The method check_input has the importing parameter iv_weight_g of type
ty_weight_g, the importing parameter iv_zone of type ty_zone, and the returning
parameter rv_reason of type ty_reason. It returns c_reason-weight if the weight
is below c_limit-min_weight or above c_limit-max_weight. Else it returns
c_reason-zone if the zone is not one of the values of c_zone. Else it returns
c_reason-ok.
7. The method base_fee has the importing parameter iv_zone of type ty_zone and
the returning parameter rv_cents of type ty_cents. It returns 350 for zone '1',
620 for zone '2', 990 for zone '3', and 0 for every other zone.
8. The method weight_surcharge has the importing parameter iv_weight_g of type
ty_weight_g and the returning parameter rv_cents of type ty_cents. It returns 0
for a weight up to 1000 grams. For every started 1000 grams above 1000 grams it
returns c_surcharge-per_step cents.
9. The method total_fee has the importing parameters iv_weight_g of type
ty_weight_g, iv_zone of type ty_zone, and iv_express of type abap_bool, and the
returning parameter rv_cents of type ty_cents. It returns 0 if check_input does
not return c_reason-ok. Else it returns base_fee plus weight_surcharge, and it
adds c_surcharge-express if iv_express is abap_true.
# 6. Constraints
- Release target: SAP_BASIS 816 (SAP ABAP Platform 2025).
- Coding standards: Clean ABAP. No global variables. No comment that restates the
code.
- Out of scope: no database table, no CDS view, no function module, no report, and
no application class.
# 7. Acceptance
- The interface {{P}}IF_PARCEL_FEE is active and has no syntax error.
- The hidden tests pass.
- Write your own ABAP Unit tests for the interface. An interface has no test
include, so create one global test class in package $TMP. The test class
implements the interface and checks the constants, the type lengths, and the
method signatures. Keep all test code in this one global class.

View File

@@ -0,0 +1,52 @@
{
"id": "G1900",
"category": "A",
"object_type": "INTF",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [],
"contract": [
{
"type": "INTF",
"name": "{{P}}IF_PARCEL_FEE"
}
],
"out_of_scope": [
"No database table",
"No CDS view",
"No function module",
"No report",
"No application class"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}PARCEL_FEE_HIDDEN",
"file": "hidden/parcel_fee_hidden.clas.abap",
"description": "Contract tests for {{P}}IF_PARCEL_FEE"
}
],
"reference": [
{
"type": "INTF",
"name": "{{P}}IF_PARCEL_FEE",
"file": "reference/if_parcel_fee.intf.abap",
"description": "Parcel fee contract"
},
{
"type": "CLAS",
"name": "{{P}}PARCEL_FEE_TEST",
"file": "reference/parcel_fee_test.clas.abap",
"description": "Own tests for the interface"
}
],
"craft_checks": [
"method_length",
"no_global_variables"
]
}