Step F first pass: 81/92 accepted; budget floor 60 calls; rejected slots moved for regeneration

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 12:10:52 +02:00
parent d3250acfb8
commit 39769afce8
741 changed files with 40573 additions and 317 deletions

View File

@@ -0,0 +1,71 @@
CLASS {{p}}driving_test_check DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_pupil_id TYPE c LENGTH 10.
TYPES ty_date TYPE d.
METHODS check
IMPORTING iv_pupil_id TYPE ty_pupil_id
iv_test_date TYPE ty_date
RAISING {{p}}cx_pupil_unknown
{{p}}cx_theory_missing
{{p}}cx_lessons_missing
{{p}}cx_fee_unpaid
{{p}}cx_recent_failure.
PRIVATE SECTION.
CONSTANTS c_min_lessons TYPE i VALUE 12.
CONSTANTS c_wait_days TYPE i VALUE 14.
CONSTANTS c_done TYPE c LENGTH 1 VALUE 'X'.
TYPES: BEGIN OF ty_pupil,
pupil_id TYPE {{p}}pupil-pupil_id,
theory_done TYPE {{p}}pupil-theory_done,
lessons_done TYPE {{p}}pupil-lessons_done,
fee_paid TYPE {{p}}pupil-fee_paid,
last_failed TYPE {{p}}pupil-last_failed,
END OF ty_pupil.
METHODS read_pupil
IMPORTING iv_pupil_id TYPE ty_pupil_id
RETURNING VALUE(rs_pupil) TYPE ty_pupil
RAISING {{p}}cx_pupil_unknown.
ENDCLASS.
CLASS {{p}}driving_test_check IMPLEMENTATION.
METHOD check.
DATA(ls_pupil) = read_pupil( iv_pupil_id ).
IF ls_pupil-theory_done = c_done.
RAISE EXCEPTION TYPE {{p}}cx_theory_missing.
ENDIF.
IF ls_pupil-lessons_done < c_min_lessons.
RAISE EXCEPTION TYPE {{p}}cx_lessons_missing
EXPORTING iv_missing = c_min_lessons - ls_pupil-lessons_done.
ENDIF.
IF ls_pupil-fee_paid <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_fee_unpaid.
ENDIF.
IF ls_pupil-last_failed IS NOT INITIAL.
DATA(lv_days) = iv_test_date - ls_pupil-last_failed.
IF lv_days < c_wait_days.
RAISE EXCEPTION TYPE {{p}}cx_recent_failure
EXPORTING iv_days_left = c_wait_days - lv_days.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD read_pupil.
SELECT SINGLE
FROM {{p}}pupil
FIELDS pupil_id, theory_done, lessons_done, fee_paid, last_failed
WHERE pupil_id = @iv_pupil_id
INTO CORRESPONDING FIELDS OF @rs_pupil.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE {{p}}cx_pupil_unknown.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,71 @@
CLASS {{p}}driving_test_check DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_pupil_id TYPE c LENGTH 10.
TYPES ty_date TYPE d.
METHODS check
IMPORTING iv_pupil_id TYPE ty_pupil_id
iv_test_date TYPE ty_date
RAISING {{p}}cx_pupil_unknown
{{p}}cx_theory_missing
{{p}}cx_lessons_missing
{{p}}cx_fee_unpaid
{{p}}cx_recent_failure.
PRIVATE SECTION.
CONSTANTS c_min_lessons TYPE i VALUE 12.
CONSTANTS c_wait_days TYPE i VALUE 14.
CONSTANTS c_done TYPE c LENGTH 1 VALUE 'X'.
TYPES: BEGIN OF ty_pupil,
pupil_id TYPE {{p}}pupil-pupil_id,
theory_done TYPE {{p}}pupil-theory_done,
lessons_done TYPE {{p}}pupil-lessons_done,
fee_paid TYPE {{p}}pupil-fee_paid,
last_failed TYPE {{p}}pupil-last_failed,
END OF ty_pupil.
METHODS read_pupil
IMPORTING iv_pupil_id TYPE ty_pupil_id
RETURNING VALUE(rs_pupil) TYPE ty_pupil
RAISING {{p}}cx_pupil_unknown.
ENDCLASS.
CLASS {{p}}driving_test_check IMPLEMENTATION.
METHOD check.
DATA(ls_pupil) = read_pupil( iv_pupil_id ).
IF ls_pupil-theory_done <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_theory_missing.
ENDIF.
IF ls_pupil-lessons_done >= c_min_lessons.
RAISE EXCEPTION TYPE {{p}}cx_lessons_missing
EXPORTING iv_missing = c_min_lessons - ls_pupil-lessons_done.
ENDIF.
IF ls_pupil-fee_paid <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_fee_unpaid.
ENDIF.
IF ls_pupil-last_failed IS NOT INITIAL.
DATA(lv_days) = iv_test_date - ls_pupil-last_failed.
IF lv_days < c_wait_days.
RAISE EXCEPTION TYPE {{p}}cx_recent_failure
EXPORTING iv_days_left = c_wait_days - lv_days.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD read_pupil.
SELECT SINGLE
FROM {{p}}pupil
FIELDS pupil_id, theory_done, lessons_done, fee_paid, last_failed
WHERE pupil_id = @iv_pupil_id
INTO CORRESPONDING FIELDS OF @rs_pupil.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE {{p}}cx_pupil_unknown.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,71 @@
CLASS {{p}}driving_test_check DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_pupil_id TYPE c LENGTH 10.
TYPES ty_date TYPE d.
METHODS check
IMPORTING iv_pupil_id TYPE ty_pupil_id
iv_test_date TYPE ty_date
RAISING {{p}}cx_pupil_unknown
{{p}}cx_theory_missing
{{p}}cx_lessons_missing
{{p}}cx_fee_unpaid
{{p}}cx_recent_failure.
PRIVATE SECTION.
CONSTANTS c_min_lessons TYPE i VALUE 12.
CONSTANTS c_wait_days TYPE i VALUE 14.
CONSTANTS c_done TYPE c LENGTH 1 VALUE 'X'.
TYPES: BEGIN OF ty_pupil,
pupil_id TYPE {{p}}pupil-pupil_id,
theory_done TYPE {{p}}pupil-theory_done,
lessons_done TYPE {{p}}pupil-lessons_done,
fee_paid TYPE {{p}}pupil-fee_paid,
last_failed TYPE {{p}}pupil-last_failed,
END OF ty_pupil.
METHODS read_pupil
IMPORTING iv_pupil_id TYPE ty_pupil_id
RETURNING VALUE(rs_pupil) TYPE ty_pupil
RAISING {{p}}cx_pupil_unknown.
ENDCLASS.
CLASS {{p}}driving_test_check IMPLEMENTATION.
METHOD check.
DATA(ls_pupil) = read_pupil( iv_pupil_id ).
IF ls_pupil-theory_done <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_theory_missing.
ENDIF.
IF ls_pupil-lessons_done < c_min_lessons.
RAISE EXCEPTION TYPE {{p}}cx_lessons_missing
EXPORTING iv_missing = c_min_lessons - ls_pupil-lessons_done.
ENDIF.
IF ls_pupil-fee_paid = c_done.
RAISE EXCEPTION TYPE {{p}}cx_fee_unpaid.
ENDIF.
IF ls_pupil-last_failed IS NOT INITIAL.
DATA(lv_days) = iv_test_date - ls_pupil-last_failed.
IF lv_days < c_wait_days.
RAISE EXCEPTION TYPE {{p}}cx_recent_failure
EXPORTING iv_days_left = c_wait_days - lv_days.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD read_pupil.
SELECT SINGLE
FROM {{p}}pupil
FIELDS pupil_id, theory_done, lessons_done, fee_paid, last_failed
WHERE pupil_id = @iv_pupil_id
INTO CORRESPONDING FIELDS OF @rs_pupil.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE {{p}}cx_pupil_unknown.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,71 @@
CLASS {{p}}driving_test_check DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_pupil_id TYPE c LENGTH 10.
TYPES ty_date TYPE d.
METHODS check
IMPORTING iv_pupil_id TYPE ty_pupil_id
iv_test_date TYPE ty_date
RAISING {{p}}cx_pupil_unknown
{{p}}cx_theory_missing
{{p}}cx_lessons_missing
{{p}}cx_fee_unpaid
{{p}}cx_recent_failure.
PRIVATE SECTION.
CONSTANTS c_min_lessons TYPE i VALUE 12.
CONSTANTS c_wait_days TYPE i VALUE 14.
CONSTANTS c_done TYPE c LENGTH 1 VALUE 'X'.
TYPES: BEGIN OF ty_pupil,
pupil_id TYPE {{p}}pupil-pupil_id,
theory_done TYPE {{p}}pupil-theory_done,
lessons_done TYPE {{p}}pupil-lessons_done,
fee_paid TYPE {{p}}pupil-fee_paid,
last_failed TYPE {{p}}pupil-last_failed,
END OF ty_pupil.
METHODS read_pupil
IMPORTING iv_pupil_id TYPE ty_pupil_id
RETURNING VALUE(rs_pupil) TYPE ty_pupil
RAISING {{p}}cx_pupil_unknown.
ENDCLASS.
CLASS {{p}}driving_test_check IMPLEMENTATION.
METHOD check.
DATA(ls_pupil) = read_pupil( iv_pupil_id ).
IF ls_pupil-theory_done <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_theory_missing.
ENDIF.
IF ls_pupil-lessons_done < c_min_lessons.
RAISE EXCEPTION TYPE {{p}}cx_lessons_missing
EXPORTING iv_missing = c_min_lessons - ls_pupil-lessons_done.
ENDIF.
IF ls_pupil-fee_paid <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_fee_unpaid.
ENDIF.
IF ls_pupil-last_failed IS NOT INITIAL.
DATA(lv_days) = iv_test_date - ls_pupil-last_failed.
IF lv_days >= c_wait_days.
RAISE EXCEPTION TYPE {{p}}cx_recent_failure
EXPORTING iv_days_left = c_wait_days - lv_days.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD read_pupil.
SELECT SINGLE
FROM {{p}}pupil
FIELDS pupil_id, theory_done, lessons_done, fee_paid, last_failed
WHERE pupil_id = @iv_pupil_id
INTO CORRESPONDING FIELDS OF @rs_pupil.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE {{p}}cx_pupil_unknown.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,71 @@
CLASS {{p}}driving_test_check DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_pupil_id TYPE c LENGTH 10.
TYPES ty_date TYPE d.
METHODS check
IMPORTING iv_pupil_id TYPE ty_pupil_id
iv_test_date TYPE ty_date
RAISING {{p}}cx_pupil_unknown
{{p}}cx_theory_missing
{{p}}cx_lessons_missing
{{p}}cx_fee_unpaid
{{p}}cx_recent_failure.
PRIVATE SECTION.
CONSTANTS c_min_lessons TYPE i VALUE 12.
CONSTANTS c_wait_days TYPE i VALUE 14.
CONSTANTS c_done TYPE c LENGTH 1 VALUE 'X'.
TYPES: BEGIN OF ty_pupil,
pupil_id TYPE {{p}}pupil-pupil_id,
theory_done TYPE {{p}}pupil-theory_done,
lessons_done TYPE {{p}}pupil-lessons_done,
fee_paid TYPE {{p}}pupil-fee_paid,
last_failed TYPE {{p}}pupil-last_failed,
END OF ty_pupil.
METHODS read_pupil
IMPORTING iv_pupil_id TYPE ty_pupil_id
RETURNING VALUE(rs_pupil) TYPE ty_pupil
RAISING {{p}}cx_pupil_unknown.
ENDCLASS.
CLASS {{p}}driving_test_check IMPLEMENTATION.
METHOD check.
DATA(ls_pupil) = read_pupil( iv_pupil_id ).
IF ls_pupil-theory_done <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_theory_missing.
ENDIF.
IF ls_pupil-lessons_done < c_min_lessons.
RAISE EXCEPTION TYPE {{p}}cx_lessons_missing
EXPORTING iv_missing = c_min_lessons - ls_pupil-lessons_done.
ENDIF.
IF ls_pupil-fee_paid <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_fee_unpaid.
ENDIF.
IF ls_pupil-last_failed IS NOT INITIAL.
DATA(lv_days) = iv_test_date - ls_pupil-last_failed.
IF lv_days < c_wait_days.
RAISE EXCEPTION TYPE {{p}}cx_recent_failure
EXPORTING iv_days_left = c_wait_days - lv_days.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD read_pupil.
SELECT SINGLE
FROM {{p}}pupil
FIELDS pupil_id, theory_done, lessons_done, fee_paid, last_failed
WHERE pupil_id <> @iv_pupil_id
INTO CORRESPONDING FIELDS OF @rs_pupil.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE {{p}}cx_pupil_unknown.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,34 @@
{
"id": "G0131",
"pool": "eval",
"object_type": "CLAS",
"category": "D",
"attempts": [
{
"stage": "bundle",
"errors": [
"seed/pupil.tabl.abap: a table needs the annotation @AbapCatalog.tableCategory (for example #TRANSPARENT, #A)",
"seed/pupil.tabl.abap: a table needs the annotation @AbapCatalog.deliveryClass (for example #TRANSPARENT, #A)"
],
"by_check": {
"static": 2
}
},
{
"stage": "validate",
"oracle": 0,
"null": 0
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 5,
"killed": 5,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,167 @@
CLASS {{p}}t_driving_check DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}driving_test_check.
DATA mo_env TYPE REF TO if_osql_test_environment.
METHODS setup.
METHODS teardown.
METHODS add_pupil
IMPORTING iv_id TYPE string
iv_theory TYPE abap_bool
iv_lessons TYPE i
iv_fee TYPE abap_bool
iv_last_failed TYPE d.
METHODS rejects_unknown_pupil FOR TESTING.
METHODS rejects_missing_theory FOR TESTING.
METHODS rejects_too_few_lessons FOR TESTING.
METHODS rejects_unpaid_fee FOR TESTING.
METHODS rejects_recent_failure FOR TESTING.
METHODS accepts_ready_pupil FOR TESTING.
METHODS first_failure_wins FOR TESTING.
METHODS failure_14_days_ago_ok FOR TESTING.
METHODS lessons_12_ok FOR TESTING.
METHODS failure_13_days_rejected FOR TESTING.
ENDCLASS.
CLASS {{p}}t_driving_check IMPLEMENTATION.
METHOD setup.
mo_env = cl_osql_test_environment=>create( VALUE #( ( '{{P}}PUPIL' ) ) ).
mo_cut = NEW {{p}}driving_test_check( ).
ENDMETHOD.
METHOD teardown.
mo_env->destroy( ).
ENDMETHOD.
METHOD add_pupil.
DATA ls_pupil TYPE {{p}}pupil.
ls_pupil-client = sy-mandt.
ls_pupil-pupil_id = iv_id.
ls_pupil-pupil_name = iv_id.
IF iv_theory = abap_true.
ls_pupil-theory_done = 'X'.
ENDIF.
ls_pupil-lessons_done = iv_lessons.
IF iv_fee = abap_true.
ls_pupil-fee_paid = 'X'.
ENDIF.
ls_pupil-last_failed = iv_last_failed.
INSERT {{p}}pupil FROM @ls_pupil.
ENDMETHOD.
METHOD rejects_unknown_pupil.
TRY.
mo_cut->check( iv_pupil_id = 'P999' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'CX_PUPIL_UNKNOWN expected' ).
CATCH {{p}}cx_pupil_unknown.
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD rejects_missing_theory.
add_pupil( iv_id = 'P001' iv_theory = abap_false iv_lessons = 20
iv_fee = abap_true iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P001' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'CX_THEORY_MISSING expected' ).
CATCH {{p}}cx_theory_missing.
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD rejects_too_few_lessons.
add_pupil( iv_id = 'P002' iv_theory = abap_true iv_lessons = 9
iv_fee = abap_true iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P002' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'CX_LESSONS_MISSING expected' ).
CATCH {{p}}cx_lessons_missing INTO DATA(lx_lessons).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lx_lessons->mv_missing ).
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD rejects_unpaid_fee.
add_pupil( iv_id = 'P003' iv_theory = abap_true iv_lessons = 18
iv_fee = abap_false iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P003' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'CX_FEE_UNPAID expected' ).
CATCH {{p}}cx_fee_unpaid.
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD rejects_recent_failure.
add_pupil( iv_id = 'P004' iv_theory = abap_true iv_lessons = 20
iv_fee = abap_true iv_last_failed = '20250127' ).
TRY.
mo_cut->check( iv_pupil_id = 'P004' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'CX_RECENT_FAILURE expected' ).
CATCH {{p}}cx_recent_failure INTO DATA(lx_recent).
cl_abap_unit_assert=>assert_equals( exp = 9 act = lx_recent->mv_days_left ).
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD accepts_ready_pupil.
add_pupil( iv_id = 'P005' iv_theory = abap_true iv_lessons = 20
iv_fee = abap_true iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P005' iv_test_date = '20250201' ).
CATCH cx_root INTO DATA(lx_error).
cl_abap_unit_assert=>fail( msg = lx_error->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD first_failure_wins.
add_pupil( iv_id = 'P006' iv_theory = abap_false iv_lessons = 5
iv_fee = abap_false iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P006' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'CX_THEORY_MISSING expected' ).
CATCH {{p}}cx_theory_missing.
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD failure_14_days_ago_ok.
add_pupil( iv_id = 'P007' iv_theory = abap_true iv_lessons = 20
iv_fee = abap_true iv_last_failed = '20250118' ).
TRY.
mo_cut->check( iv_pupil_id = 'P007' iv_test_date = '20250201' ).
CATCH cx_root INTO DATA(lx_error).
cl_abap_unit_assert=>fail( msg = lx_error->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD lessons_12_ok.
add_pupil( iv_id = 'P008' iv_theory = abap_true iv_lessons = 12
iv_fee = abap_true iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P008' iv_test_date = '20250201' ).
CATCH cx_root INTO DATA(lx_error).
cl_abap_unit_assert=>fail( msg = lx_error->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD failure_13_days_rejected.
add_pupil( iv_id = 'P009' iv_theory = abap_true iv_lessons = 20
iv_fee = abap_true iv_last_failed = '20250119' ).
TRY.
mo_cut->check( iv_pupil_id = 'P009' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'CX_RECENT_FAILURE expected' ).
CATCH {{p}}cx_recent_failure INTO DATA(lx_recent).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lx_recent->mv_days_left ).
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,83 @@
{
"task": "G0131",
"mutants": [
{
"object": "{{P}}DRIVING_TEST_CHECK",
"mutant": "line 39: <> -> = (rel)",
"status": "killed",
"hidden": "1/10",
"failed_tests": [
"ACCEPTS_READY_PUPIL",
"FAILURE_13_DAYS_REJECTED",
"FAILURE_14_DAYS_AGO_OK",
"FIRST_FAILURE_WINS",
"LESSONS_12_OK",
"REJECTS_MISSING_THEORY",
"REJECTS_RECENT_FAILURE",
"REJECTS_TOO_FEW_LESSONS",
"REJECTS_UNPAID_FEE"
]
},
{
"object": "{{P}}DRIVING_TEST_CHECK",
"mutant": "line 43: < -> >= (rel)",
"status": "killed",
"hidden": "3/10",
"failed_tests": [
"ACCEPTS_READY_PUPIL",
"FAILURE_13_DAYS_REJECTED",
"FAILURE_14_DAYS_AGO_OK",
"LESSONS_12_OK",
"REJECTS_RECENT_FAILURE",
"REJECTS_TOO_FEW_LESSONS",
"REJECTS_UNPAID_FEE"
]
},
{
"object": "{{P}}DRIVING_TEST_CHECK",
"mutant": "line 48: <> -> = (rel)",
"status": "killed",
"hidden": "4/10",
"failed_tests": [
"ACCEPTS_READY_PUPIL",
"FAILURE_13_DAYS_REJECTED",
"FAILURE_14_DAYS_AGO_OK",
"LESSONS_12_OK",
"REJECTS_RECENT_FAILURE",
"REJECTS_UNPAID_FEE"
]
},
{
"object": "{{P}}DRIVING_TEST_CHECK",
"mutant": "line 54: < -> >= (rel)",
"status": "killed",
"hidden": "7/10",
"failed_tests": [
"FAILURE_13_DAYS_REJECTED",
"FAILURE_14_DAYS_AGO_OK",
"REJECTS_RECENT_FAILURE"
]
},
{
"object": "{{P}}DRIVING_TEST_CHECK",
"mutant": "line 65: = -> <> (eq)",
"status": "killed",
"hidden": "1/10",
"failed_tests": [
"ACCEPTS_READY_PUPIL",
"FAILURE_13_DAYS_REJECTED",
"FAILURE_14_DAYS_AGO_OK",
"FIRST_FAILURE_WINS",
"LESSONS_12_OK",
"REJECTS_MISSING_THEORY",
"REJECTS_RECENT_FAILURE",
"REJECTS_TOO_FEW_LESSONS",
"REJECTS_UNPAID_FEE"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

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

View File

@@ -0,0 +1,14 @@
CLASS {{p}}cx_lessons_missing DEFINITION PUBLIC FINAL CREATE PUBLIC INHERITING FROM cx_static_check.
PUBLIC SECTION.
DATA mv_missing TYPE i READ-ONLY.
METHODS constructor
IMPORTING iv_missing TYPE i.
ENDCLASS.
CLASS {{p}}cx_lessons_missing IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mv_missing = iv_missing.
ENDMETHOD.
ENDCLASS.

View File

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

View File

@@ -0,0 +1,14 @@
CLASS {{p}}cx_recent_failure DEFINITION PUBLIC FINAL CREATE PUBLIC INHERITING FROM cx_static_check.
PUBLIC SECTION.
DATA mv_days_left TYPE i READ-ONLY.
METHODS constructor
IMPORTING iv_days_left TYPE i.
ENDCLASS.
CLASS {{p}}cx_recent_failure IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
mv_days_left = iv_days_left.
ENDMETHOD.
ENDCLASS.

View File

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

View File

@@ -0,0 +1,71 @@
CLASS {{p}}driving_test_check DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_pupil_id TYPE c LENGTH 10.
TYPES ty_date TYPE d.
METHODS check
IMPORTING iv_pupil_id TYPE ty_pupil_id
iv_test_date TYPE ty_date
RAISING {{p}}cx_pupil_unknown
{{p}}cx_theory_missing
{{p}}cx_lessons_missing
{{p}}cx_fee_unpaid
{{p}}cx_recent_failure.
PRIVATE SECTION.
CONSTANTS c_min_lessons TYPE i VALUE 12.
CONSTANTS c_wait_days TYPE i VALUE 14.
CONSTANTS c_done TYPE c LENGTH 1 VALUE 'X'.
TYPES: BEGIN OF ty_pupil,
pupil_id TYPE {{p}}pupil-pupil_id,
theory_done TYPE {{p}}pupil-theory_done,
lessons_done TYPE {{p}}pupil-lessons_done,
fee_paid TYPE {{p}}pupil-fee_paid,
last_failed TYPE {{p}}pupil-last_failed,
END OF ty_pupil.
METHODS read_pupil
IMPORTING iv_pupil_id TYPE ty_pupil_id
RETURNING VALUE(rs_pupil) TYPE ty_pupil
RAISING {{p}}cx_pupil_unknown.
ENDCLASS.
CLASS {{p}}driving_test_check IMPLEMENTATION.
METHOD check.
DATA(ls_pupil) = read_pupil( iv_pupil_id ).
IF ls_pupil-theory_done <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_theory_missing.
ENDIF.
IF ls_pupil-lessons_done < c_min_lessons.
RAISE EXCEPTION TYPE {{p}}cx_lessons_missing
EXPORTING iv_missing = c_min_lessons - ls_pupil-lessons_done.
ENDIF.
IF ls_pupil-fee_paid <> c_done.
RAISE EXCEPTION TYPE {{p}}cx_fee_unpaid.
ENDIF.
IF ls_pupil-last_failed IS NOT INITIAL.
DATA(lv_days) = iv_test_date - ls_pupil-last_failed.
IF lv_days < c_wait_days.
RAISE EXCEPTION TYPE {{p}}cx_recent_failure
EXPORTING iv_days_left = c_wait_days - lv_days.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD read_pupil.
SELECT SINGLE
FROM {{p}}pupil
FIELDS pupil_id, theory_done, lessons_done, fee_paid, last_failed
WHERE pupil_id = @iv_pupil_id
INTO CORRESPONDING FIELDS OF @rs_pupil.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE {{p}}cx_pupil_unknown.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,117 @@
CLASS ltc_driving_test_check DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO {{p}}driving_test_check.
DATA mo_env TYPE REF TO if_osql_test_environment.
METHODS setup.
METHODS teardown.
METHODS add_pupil
IMPORTING iv_id TYPE string
iv_theory TYPE abap_bool
iv_lessons TYPE i
iv_fee TYPE abap_bool
iv_last_failed TYPE d.
METHODS ready_pupil_passes FOR TESTING.
METHODS unknown_pupil_raises FOR TESTING.
METHODS missing_theory_raises FOR TESTING.
METHODS few_lessons_raise FOR TESTING.
METHODS unpaid_fee_raises FOR TESTING.
METHODS recent_failure_raises FOR TESTING.
ENDCLASS.
CLASS ltc_driving_test_check IMPLEMENTATION.
METHOD setup.
mo_env = cl_osql_test_environment=>create( VALUE #( ( '{{P}}PUPIL' ) ) ).
mo_cut = NEW {{p}}driving_test_check( ).
ENDMETHOD.
METHOD teardown.
mo_env->destroy( ).
ENDMETHOD.
METHOD add_pupil.
DATA ls_pupil TYPE {{p}}pupil.
ls_pupil-client = sy-mandt.
ls_pupil-pupil_id = iv_id.
ls_pupil-pupil_name = iv_id.
IF iv_theory = abap_true.
ls_pupil-theory_done = 'X'.
ENDIF.
ls_pupil-lessons_done = iv_lessons.
IF iv_fee = abap_true.
ls_pupil-fee_paid = 'X'.
ENDIF.
ls_pupil-last_failed = iv_last_failed.
INSERT {{p}}pupil FROM @ls_pupil.
ENDMETHOD.
METHOD ready_pupil_passes.
add_pupil( iv_id = 'P001' iv_theory = abap_true iv_lessons = 20
iv_fee = abap_true iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P001' iv_test_date = '20250201' ).
CATCH cx_root INTO DATA(lx_error).
cl_abap_unit_assert=>fail( msg = lx_error->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD unknown_pupil_raises.
TRY.
mo_cut->check( iv_pupil_id = 'P999' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'exception expected' ).
CATCH {{p}}cx_pupil_unknown.
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD missing_theory_raises.
add_pupil( iv_id = 'P002' iv_theory = abap_false iv_lessons = 20
iv_fee = abap_true iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P002' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'exception expected' ).
CATCH {{p}}cx_theory_missing.
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD few_lessons_raise.
add_pupil( iv_id = 'P003' iv_theory = abap_true iv_lessons = 9
iv_fee = abap_true iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P003' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'exception expected' ).
CATCH {{p}}cx_lessons_missing INTO DATA(lx_lessons).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lx_lessons->mv_missing ).
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD unpaid_fee_raises.
add_pupil( iv_id = 'P004' iv_theory = abap_true iv_lessons = 20
iv_fee = abap_false iv_last_failed = '00000000' ).
TRY.
mo_cut->check( iv_pupil_id = 'P004' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'exception expected' ).
CATCH {{p}}cx_fee_unpaid.
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD recent_failure_raises.
add_pupil( iv_id = 'P005' iv_theory = abap_true iv_lessons = 20
iv_fee = abap_true iv_last_failed = '20250127' ).
TRY.
mo_cut->check( iv_pupil_id = 'P005' iv_test_date = '20250201' ).
cl_abap_unit_assert=>fail( msg = 'exception expected' ).
CATCH {{p}}cx_recent_failure INTO DATA(lx_recent).
cl_abap_unit_assert=>assert_equals( exp = 9 act = lx_recent->mv_days_left ).
CATCH cx_root INTO DATA(lx_wrong).
cl_abap_unit_assert=>fail( msg = lx_wrong->get_text( ) ).
ENDTRY.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,13 @@
@EndUserText.label : 'Pupil'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
define table {{p}}pupil {
key client : abap.clnt not null;
key pupil_id : abap.char(10) not null;
pupil_name : abap.char(40);
theory_done : abap.char(1);
lessons_done : abap.int4;
fee_paid : abap.char(1);
last_failed : abap.dats;
}

View File

@@ -0,0 +1,24 @@
CLASS {{p}}pupil_data DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS {{p}}pupil_data IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DELETE FROM {{p}}pupil.
INSERT {{p}}pupil FROM TABLE @( VALUE #(
( client = sy-mandt pupil_id = 'P001' pupil_name = 'Anna Adler'
theory_done = 'X' lessons_done = 20 fee_paid = 'X' last_failed = '00000000' )
( client = sy-mandt pupil_id = 'P002' pupil_name = 'Bodo Berger'
theory_done = '' lessons_done = 15 fee_paid = 'X' last_failed = '00000000' )
( client = sy-mandt pupil_id = 'P003' pupil_name = 'Carla Conrad'
theory_done = 'X' lessons_done = 5 fee_paid = 'X' last_failed = '00000000' )
( client = sy-mandt pupil_id = 'P004' pupil_name = 'Dana Decker'
theory_done = 'X' lessons_done = 18 fee_paid = '' last_failed = '00000000' )
( client = sy-mandt pupil_id = 'P005' pupil_name = 'Emil Ebert'
theory_done = 'X' lessons_done = 25 fee_paid = 'X' last_failed = '20250127' )
) ).
out->write( 'Pupil data written' ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,73 @@
# 1. Goal
A driving school checks if a pupil may book a practical driving test. A booking
program calls the check before it books the test. When the pupil is not ready,
the check must tell the program the exact reason.
# 2. Open questions
None.
# 3. Context
- The table {{P}}PUPIL exists in package $TMP. It is active.
- The table has these fields: CLIENT, PUPIL_ID (character 10), PUPIL_NAME
(character 40), THEORY_DONE (character 1), LESSONS_DONE (integer), FEE_PAID
(character 1), LAST_FAILED (date).
- THEORY_DONE and FEE_PAID contain 'X' when the item is done. They are initial
when the item is not done.
- LESSONS_DONE is the number of driving lessons that the pupil completed.
- LAST_FAILED is the date of the last failed practical test. It is initial when
the pupil never failed a test.
- The class {{P}}PUPIL_DATA fills the table with example data. It is active.
# 4. Contract
Create the class {{P}}DRIVING_TEST_CHECK in package $TMP.
- The class is public, final, and has a public constructor without parameters.
- Define these types in the public section of the class:
TYPES ty_pupil_id TYPE c LENGTH 10.
TYPES ty_date TYPE d.
- The class has this public method and no other public method:
METHODS check
IMPORTING iv_pupil_id TYPE ty_pupil_id
iv_test_date TYPE ty_date
RAISING {{P}}CX_PUPIL_UNKNOWN
{{P}}CX_THEORY_MISSING
{{P}}CX_LESSONS_MISSING
{{P}}CX_FEE_UNPAID
{{P}}CX_RECENT_FAILURE.
- Create these exception classes in package $TMP. Each class is public and
inherits from CX_STATIC_CHECK.
- {{P}}CX_PUPIL_UNKNOWN: no constructor parameter.
- {{P}}CX_THEORY_MISSING: no constructor parameter.
- {{P}}CX_LESSONS_MISSING: constructor parameter IV_MISSING TYPE i. The
public read-only attribute MV_MISSING TYPE i has the value of IV_MISSING.
- {{P}}CX_FEE_UNPAID: no constructor parameter.
- {{P}}CX_RECENT_FAILURE: constructor parameter IV_DAYS_LEFT TYPE i. The
public read-only attribute MV_DAYS_LEFT TYPE i has the value of
IV_DAYS_LEFT.
- Do not add other public methods or attributes to these classes.
# 5. Business rules
The method CHECK reads the pupil with the pupil id IV_PUPIL_ID from the table
{{P}}PUPIL. Apply these rules in this sequence. Raise the exception of the
first rule that fails. Raise no exception when all rules pass.
1. If the table has no entry for this pupil id, raise {{P}}CX_PUPIL_UNKNOWN.
2. If THEORY_DONE is not 'X', raise {{P}}CX_THEORY_MISSING.
3. If LESSONS_DONE is less than 12, raise {{P}}CX_LESSONS_MISSING with
IV_MISSING = 12 - LESSONS_DONE.
4. If FEE_PAID is not 'X', raise {{P}}CX_FEE_UNPAID.
5. If LAST_FAILED is not initial, calculate the number of days from LAST_FAILED
to IV_TEST_DATE. If this number is less than 14, raise
{{P}}CX_RECENT_FAILURE with IV_DAYS_LEFT = 14 - number of days.
# 6. Constraints
- Release target: 8.16.
- Coding standards: Clean ABAP. Methods below 40 statements. No global
variables. Pass large parameters by reference. No comment that restates the
code.
- A test must not pass when the method under test raises an exception that the
test does not expect.
- Out of scope: do not change {{P}}PUPIL and {{P}}PUPIL_DATA.
# 7. Acceptance
- All classes are active and have no syntax error.
- The hidden tests pass.
- Write your own ABAP Unit tests for the class {{P}}DRIVING_TEST_CHECK.

View File

@@ -0,0 +1,108 @@
{
"id": "G0131",
"category": "D",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "TABL",
"name": "{{P}}PUPIL",
"file": "seed/pupil.tabl.abap",
"description": "Pupil master data of the driving school"
},
{
"type": "CLAS",
"name": "{{P}}PUPIL_DATA",
"file": "seed/pupil_data.clas.abap",
"description": "Fills the pupil table with example data",
"run": true
}
],
"contract": [
{
"type": "CLAS",
"name": "{{P}}DRIVING_TEST_CHECK"
},
{
"type": "CLAS",
"name": "{{P}}CX_PUPIL_UNKNOWN"
},
{
"type": "CLAS",
"name": "{{P}}CX_THEORY_MISSING"
},
{
"type": "CLAS",
"name": "{{P}}CX_LESSONS_MISSING"
},
{
"type": "CLAS",
"name": "{{P}}CX_FEE_UNPAID"
},
{
"type": "CLAS",
"name": "{{P}}CX_RECENT_FAILURE"
}
],
"out_of_scope": [
"{{P}}PUPIL",
"{{P}}PUPIL_DATA"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T_DRIVING_CHECK",
"file": "hidden/t_driving_check.clas.abap",
"description": "Hidden tests for the driving test booking check"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}CX_PUPIL_UNKNOWN",
"file": "reference/cx_pupil_unknown.clas.abap",
"description": "Pupil id is not in the pupil table"
},
{
"type": "CLAS",
"name": "{{P}}CX_THEORY_MISSING",
"file": "reference/cx_theory_missing.clas.abap",
"description": "Theory exam is not passed"
},
{
"type": "CLAS",
"name": "{{P}}CX_LESSONS_MISSING",
"file": "reference/cx_lessons_missing.clas.abap",
"description": "Too few driving lessons"
},
{
"type": "CLAS",
"name": "{{P}}CX_FEE_UNPAID",
"file": "reference/cx_fee_unpaid.clas.abap",
"description": "Test fee is not paid"
},
{
"type": "CLAS",
"name": "{{P}}CX_RECENT_FAILURE",
"file": "reference/cx_recent_failure.clas.abap",
"description": "Last practical test failed too recently"
},
{
"type": "CLAS",
"name": "{{P}}DRIVING_TEST_CHECK",
"file": "reference/driving_test_check.clas.abap",
"description": "Checks if a pupil may book a practical driving test",
"testclasses_file": "reference/driving_test_check.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"db_operation_in_loop"
]
}