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,102 @@
CLASS {{p}}app_scorer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 4.
TYPES: BEGIN OF ty_result,
status TYPE ty_status,
score TYPE i,
rating TYPE string,
END OF ty_result.
CONSTANTS: BEGIN OF co_status,
ok TYPE ty_status VALUE 'OK',
bad_years TYPE ty_status VALUE 'YEAR',
bad_match TYPE ty_status VALUE 'MATC',
bad_degree TYPE ty_status VALUE 'DEGR',
END OF co_status.
METHODS evaluate
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
RETURNING
VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
METHODS experience_points
IMPORTING iv_years TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS education_points
IMPORTING iv_degree TYPE string
RETURNING VALUE(rv_points) TYPE i.
METHODS skill_points
IMPORTING iv_match TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS rating_for
IMPORTING iv_score TYPE i
RETURNING VALUE(rv_rating) TYPE string.
ENDCLASS.
CLASS {{p}}app_scorer IMPLEMENTATION.
METHOD evaluate.
rs_result = VALUE #( status = co_status-ok ).
IF iv_years < 0.
rs_result-status = co_status-bad_years.
RETURN.
ENDIF.
IF iv_match < 0 AND iv_match > 100.
rs_result-status = co_status-bad_match.
RETURN.
ENDIF.
DATA(lv_education) = education_points( iv_degree ).
IF lv_education < 0.
rs_result-status = co_status-bad_degree.
RETURN.
ENDIF.
rs_result-score = experience_points( iv_years ) + lv_education + skill_points( iv_match ).
rs_result-rating = rating_for( rs_result-score ).
ENDMETHOD.
METHOD experience_points.
rv_points = iv_years * 8.
IF rv_points > 40.
rv_points = 40.
ENDIF.
ENDMETHOD.
METHOD education_points.
CASE iv_degree.
WHEN 'PHD'.
rv_points = 30.
WHEN 'MAS'.
rv_points = 25.
WHEN 'BAC'.
rv_points = 20.
WHEN 'VOC'.
rv_points = 10.
WHEN OTHERS.
rv_points = -1.
ENDCASE.
ENDMETHOD.
METHOD skill_points.
rv_points = ( iv_match * 30 + 50 ) DIV 100.
ENDMETHOD.
METHOD rating_for.
IF iv_score >= 75.
rv_rating = 'INVITE'.
ELSEIF iv_score >= 50.
rv_rating = 'REVIEW'.
ELSE.
rv_rating = 'REJECT'.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,31 @@
FUNCTION {{p}}appl_score
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
EXPORTING
ev_score TYPE i
ev_rating TYPE string
EXCEPTIONS
invalid_years
invalid_match
invalid_degree.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate(
iv_years = iv_years
iv_degree = iv_degree
iv_match = iv_match ).
IF ls_result-status <> {{p}}app_scorer=>co_status-bad_years.
RAISE invalid_years.
ELSEIF ls_result-status = {{p}}app_scorer=>co_status-bad_match.
RAISE invalid_match.
ELSEIF ls_result-status = {{p}}app_scorer=>co_status-bad_degree.
RAISE invalid_degree.
ENDIF.
ev_score = ls_result-score.
ev_rating = ls_result-rating.
ENDFUNCTION.

View File

@@ -0,0 +1,102 @@
CLASS {{p}}app_scorer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 4.
TYPES: BEGIN OF ty_result,
status TYPE ty_status,
score TYPE i,
rating TYPE string,
END OF ty_result.
CONSTANTS: BEGIN OF co_status,
ok TYPE ty_status VALUE 'OK',
bad_years TYPE ty_status VALUE 'YEAR',
bad_match TYPE ty_status VALUE 'MATC',
bad_degree TYPE ty_status VALUE 'DEGR',
END OF co_status.
METHODS evaluate
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
RETURNING
VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
METHODS experience_points
IMPORTING iv_years TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS education_points
IMPORTING iv_degree TYPE string
RETURNING VALUE(rv_points) TYPE i.
METHODS skill_points
IMPORTING iv_match TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS rating_for
IMPORTING iv_score TYPE i
RETURNING VALUE(rv_rating) TYPE string.
ENDCLASS.
CLASS {{p}}app_scorer IMPLEMENTATION.
METHOD evaluate.
rs_result = VALUE #( status = co_status-ok ).
IF iv_years < 0.
rs_result-status = co_status-bad_years.
RETURN.
ENDIF.
IF iv_match < 0 OR iv_match <= 100.
rs_result-status = co_status-bad_match.
RETURN.
ENDIF.
DATA(lv_education) = education_points( iv_degree ).
IF lv_education < 0.
rs_result-status = co_status-bad_degree.
RETURN.
ENDIF.
rs_result-score = experience_points( iv_years ) + lv_education + skill_points( iv_match ).
rs_result-rating = rating_for( rs_result-score ).
ENDMETHOD.
METHOD experience_points.
rv_points = iv_years * 8.
IF rv_points > 40.
rv_points = 40.
ENDIF.
ENDMETHOD.
METHOD education_points.
CASE iv_degree.
WHEN 'PHD'.
rv_points = 30.
WHEN 'MAS'.
rv_points = 25.
WHEN 'BAC'.
rv_points = 20.
WHEN 'VOC'.
rv_points = 10.
WHEN OTHERS.
rv_points = -1.
ENDCASE.
ENDMETHOD.
METHOD skill_points.
rv_points = ( iv_match * 30 + 50 ) DIV 100.
ENDMETHOD.
METHOD rating_for.
IF iv_score >= 75.
rv_rating = 'INVITE'.
ELSEIF iv_score >= 50.
rv_rating = 'REVIEW'.
ELSE.
rv_rating = 'REJECT'.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,31 @@
FUNCTION {{p}}appl_score
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
EXPORTING
ev_score TYPE i
ev_rating TYPE string
EXCEPTIONS
invalid_years
invalid_match
invalid_degree.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate(
iv_years = iv_years
iv_degree = iv_degree
iv_match = iv_match ).
IF ls_result-status = {{p}}app_scorer=>co_status-bad_years.
RAISE invalid_years.
ELSEIF ls_result-status <> {{p}}app_scorer=>co_status-bad_match.
RAISE invalid_match.
ELSEIF ls_result-status = {{p}}app_scorer=>co_status-bad_degree.
RAISE invalid_degree.
ENDIF.
ev_score = ls_result-score.
ev_rating = ls_result-rating.
ENDFUNCTION.

View File

@@ -0,0 +1,102 @@
CLASS {{p}}app_scorer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 4.
TYPES: BEGIN OF ty_result,
status TYPE ty_status,
score TYPE i,
rating TYPE string,
END OF ty_result.
CONSTANTS: BEGIN OF co_status,
ok TYPE ty_status VALUE 'OK',
bad_years TYPE ty_status VALUE 'YEAR',
bad_match TYPE ty_status VALUE 'MATC',
bad_degree TYPE ty_status VALUE 'DEGR',
END OF co_status.
METHODS evaluate
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
RETURNING
VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
METHODS experience_points
IMPORTING iv_years TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS education_points
IMPORTING iv_degree TYPE string
RETURNING VALUE(rv_points) TYPE i.
METHODS skill_points
IMPORTING iv_match TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS rating_for
IMPORTING iv_score TYPE i
RETURNING VALUE(rv_rating) TYPE string.
ENDCLASS.
CLASS {{p}}app_scorer IMPLEMENTATION.
METHOD evaluate.
rs_result = VALUE #( status = co_status-ok ).
IF iv_years < 0.
rs_result-status = co_status-bad_years.
RETURN.
ENDIF.
IF iv_match < 0 OR iv_match > 100.
rs_result-status = co_status-bad_match.
RETURN.
ENDIF.
DATA(lv_education) = education_points( iv_degree ).
IF lv_education >= 0.
rs_result-status = co_status-bad_degree.
RETURN.
ENDIF.
rs_result-score = experience_points( iv_years ) + lv_education + skill_points( iv_match ).
rs_result-rating = rating_for( rs_result-score ).
ENDMETHOD.
METHOD experience_points.
rv_points = iv_years * 8.
IF rv_points > 40.
rv_points = 40.
ENDIF.
ENDMETHOD.
METHOD education_points.
CASE iv_degree.
WHEN 'PHD'.
rv_points = 30.
WHEN 'MAS'.
rv_points = 25.
WHEN 'BAC'.
rv_points = 20.
WHEN 'VOC'.
rv_points = 10.
WHEN OTHERS.
rv_points = -1.
ENDCASE.
ENDMETHOD.
METHOD skill_points.
rv_points = ( iv_match * 30 + 50 ) DIV 100.
ENDMETHOD.
METHOD rating_for.
IF iv_score >= 75.
rv_rating = 'INVITE'.
ELSEIF iv_score >= 50.
rv_rating = 'REVIEW'.
ELSE.
rv_rating = 'REJECT'.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,19 @@
{
"id": "G0106",
"pool": "eval",
"object_type": "FUNC",
"category": "A",
"attempts": [
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 5,
"killed": 5,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,138 @@
CLASS {{p}}t41_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS call_score
IMPORTING iv_years TYPE i iv_degree TYPE string iv_match TYPE i
EXPORTING ev_score TYPE i ev_rating TYPE string ev_subrc TYPE sysubrc.
METHODS class_experience_points FOR TESTING.
METHODS class_education_points FOR TESTING.
METHODS class_skill_rounding FOR TESTING.
METHODS class_rating_limits FOR TESTING.
METHODS class_invalid_years FOR TESTING.
METHODS class_invalid_match FOR TESTING.
METHODS class_invalid_degree FOR TESTING.
METHODS func_returns_result FOR TESTING.
METHODS func_raises_years FOR TESTING.
METHODS func_raises_match FOR TESTING.
METHODS func_raises_degree FOR TESTING.
ENDCLASS.
CLASS {{p}}t41_hidden IMPLEMENTATION.
METHOD call_score.
CLEAR: ev_score, ev_rating.
CALL FUNCTION '{{P}}APPL_SCORE'
EXPORTING
iv_years = iv_years
iv_degree = iv_degree
iv_match = iv_match
IMPORTING
ev_score = ev_score
ev_rating = ev_rating
EXCEPTIONS
invalid_years = 1
invalid_match = 2
invalid_degree = 3
OTHERS = 4.
ev_subrc = sy-subrc.
ENDMETHOD.
METHOD class_experience_points.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_two) = lo_scorer->evaluate( iv_years = 2 iv_degree = 'VOC' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 26 act = ls_two-score ).
DATA(ls_cap) = lo_scorer->evaluate( iv_years = 9 iv_degree = 'VOC' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 50 act = ls_cap-score ).
ENDMETHOD.
METHOD class_education_points.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_phd) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'PHD' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 30 act = ls_phd-score ).
DATA(ls_mas) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'MAS' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 25 act = ls_mas-score ).
DATA(ls_bac) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'BAC' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 20 act = ls_bac-score ).
DATA(ls_voc) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'VOC' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 10 act = ls_voc-score ).
ENDMETHOD.
METHOD class_skill_rounding.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_full) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'VOC' iv_match = 100 ).
cl_abap_unit_assert=>assert_equals( exp = 40 act = ls_full-score ).
DATA(ls_half) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'VOC' iv_match = 35 ).
cl_abap_unit_assert=>assert_equals( exp = 21 act = ls_half-score ).
DATA(ls_down) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'VOC' iv_match = 33 ).
cl_abap_unit_assert=>assert_equals( exp = 20 act = ls_down-score ).
DATA(ls_low) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'VOC' iv_match = 1 ).
cl_abap_unit_assert=>assert_equals( exp = 10 act = ls_low-score ).
ENDMETHOD.
METHOD class_rating_limits.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_invite) = lo_scorer->evaluate( iv_years = 5 iv_degree = 'MAS' iv_match = 33 ).
cl_abap_unit_assert=>assert_equals( exp = 75 act = ls_invite-score ).
cl_abap_unit_assert=>assert_equals( exp = 'INVITE' act = ls_invite-rating ).
DATA(ls_review) = lo_scorer->evaluate( iv_years = 5 iv_degree = 'MAS' iv_match = 30 ).
cl_abap_unit_assert=>assert_equals( exp = 74 act = ls_review-score ).
cl_abap_unit_assert=>assert_equals( exp = 'REVIEW' act = ls_review-rating ).
DATA(ls_edge) = lo_scorer->evaluate( iv_years = 5 iv_degree = 'VOC' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 50 act = ls_edge-score ).
cl_abap_unit_assert=>assert_equals( exp = 'REVIEW' act = ls_edge-rating ).
DATA(ls_low) = lo_scorer->evaluate( iv_years = 3 iv_degree = 'MAS' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 49 act = ls_low-score ).
cl_abap_unit_assert=>assert_equals( exp = 'REJECT' act = ls_low-rating ).
ENDMETHOD.
METHOD class_invalid_years.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate( iv_years = -1 iv_degree = 'PHD' iv_match = 100 ).
cl_abap_unit_assert=>assert_equals( exp = 'YEAR' act = ls_result-status ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_result-score ).
cl_abap_unit_assert=>assert_initial( act = ls_result-rating ).
ENDMETHOD.
METHOD class_invalid_match.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_high) = lo_scorer->evaluate( iv_years = 1 iv_degree = 'PHD' iv_match = 101 ).
cl_abap_unit_assert=>assert_equals( exp = 'MATC' act = ls_high-status ).
DATA(ls_low) = lo_scorer->evaluate( iv_years = 1 iv_degree = 'PHD' iv_match = -1 ).
cl_abap_unit_assert=>assert_equals( exp = 'MATC' act = ls_low-status ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = ls_low-score ).
ENDMETHOD.
METHOD class_invalid_degree.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate( iv_years = 1 iv_degree = 'XYZ' iv_match = 50 ).
cl_abap_unit_assert=>assert_equals( exp = 'DEGR' act = ls_result-status ).
cl_abap_unit_assert=>assert_initial( act = ls_result-rating ).
ENDMETHOD.
METHOD func_returns_result.
call_score( EXPORTING iv_years = 5 iv_degree = 'PHD' iv_match = 100
IMPORTING ev_score = DATA(lv_score) ev_rating = DATA(lv_rating) ev_subrc = DATA(lv_rc) ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_rc ).
cl_abap_unit_assert=>assert_equals( exp = 100 act = lv_score ).
cl_abap_unit_assert=>assert_equals( exp = 'INVITE' act = lv_rating ).
ENDMETHOD.
METHOD func_raises_years.
call_score( EXPORTING iv_years = -3 iv_degree = 'PHD' iv_match = 100
IMPORTING ev_subrc = DATA(lv_rc) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_rc ).
ENDMETHOD.
METHOD func_raises_match.
call_score( EXPORTING iv_years = 5 iv_degree = 'PHD' iv_match = 200
IMPORTING ev_subrc = DATA(lv_rc) ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lv_rc ).
ENDMETHOD.
METHOD func_raises_degree.
call_score( EXPORTING iv_years = 5 iv_degree = 'ABC' iv_match = 100
IMPORTING ev_subrc = DATA(lv_rc) ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lv_rc ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,74 @@
{
"task": "G0106",
"mutants": [
{
"object": "{{P}}APP_SCORER",
"mutant": "line 52: OR -> AND (logic)",
"status": "killed",
"hidden": "9/11",
"failed_tests": [
"CLASS_INVALID_MATCH",
"FUNC_RAISES_MATCH"
]
},
{
"object": "{{P}}APPL_SCORE",
"mutant": "line 20: = -> <> (eq)",
"status": "killed",
"hidden": "7/11",
"failed_tests": [
"FUNC_RAISES_DEGREE",
"FUNC_RAISES_MATCH",
"FUNC_RAISES_YEARS",
"FUNC_RETURNS_RESULT"
]
},
{
"object": "{{P}}APP_SCORER",
"mutant": "line 52: > -> <= (rel)",
"status": "killed",
"hidden": "2/11",
"failed_tests": [
"CLASS_EDUCATION_POINTS",
"CLASS_EXPERIENCE_POINTS",
"CLASS_INVALID_DEGREE",
"CLASS_INVALID_MATCH",
"CLASS_RATING_LIMITS",
"CLASS_SKILL_ROUNDING",
"FUNC_RAISES_DEGREE",
"FUNC_RAISES_MATCH",
"FUNC_RETURNS_RESULT"
]
},
{
"object": "{{P}}APPL_SCORE",
"mutant": "line 22: = -> <> (eq)",
"status": "killed",
"hidden": "8/11",
"failed_tests": [
"FUNC_RAISES_DEGREE",
"FUNC_RAISES_MATCH",
"FUNC_RETURNS_RESULT"
]
},
{
"object": "{{P}}APP_SCORER",
"mutant": "line 58: < -> >= (rel)",
"status": "killed",
"hidden": "4/11",
"failed_tests": [
"CLASS_EDUCATION_POINTS",
"CLASS_EXPERIENCE_POINTS",
"CLASS_INVALID_DEGREE",
"CLASS_RATING_LIMITS",
"CLASS_SKILL_ROUNDING",
"FUNC_RAISES_DEGREE",
"FUNC_RETURNS_RESULT"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,102 @@
CLASS {{p}}app_scorer DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_status TYPE c LENGTH 4.
TYPES: BEGIN OF ty_result,
status TYPE ty_status,
score TYPE i,
rating TYPE string,
END OF ty_result.
CONSTANTS: BEGIN OF co_status,
ok TYPE ty_status VALUE 'OK',
bad_years TYPE ty_status VALUE 'YEAR',
bad_match TYPE ty_status VALUE 'MATC',
bad_degree TYPE ty_status VALUE 'DEGR',
END OF co_status.
METHODS evaluate
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
RETURNING
VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
METHODS experience_points
IMPORTING iv_years TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS education_points
IMPORTING iv_degree TYPE string
RETURNING VALUE(rv_points) TYPE i.
METHODS skill_points
IMPORTING iv_match TYPE i
RETURNING VALUE(rv_points) TYPE i.
METHODS rating_for
IMPORTING iv_score TYPE i
RETURNING VALUE(rv_rating) TYPE string.
ENDCLASS.
CLASS {{p}}app_scorer IMPLEMENTATION.
METHOD evaluate.
rs_result = VALUE #( status = co_status-ok ).
IF iv_years < 0.
rs_result-status = co_status-bad_years.
RETURN.
ENDIF.
IF iv_match < 0 OR iv_match > 100.
rs_result-status = co_status-bad_match.
RETURN.
ENDIF.
DATA(lv_education) = education_points( iv_degree ).
IF lv_education < 0.
rs_result-status = co_status-bad_degree.
RETURN.
ENDIF.
rs_result-score = experience_points( iv_years ) + lv_education + skill_points( iv_match ).
rs_result-rating = rating_for( rs_result-score ).
ENDMETHOD.
METHOD experience_points.
rv_points = iv_years * 8.
IF rv_points > 40.
rv_points = 40.
ENDIF.
ENDMETHOD.
METHOD education_points.
CASE iv_degree.
WHEN 'PHD'.
rv_points = 30.
WHEN 'MAS'.
rv_points = 25.
WHEN 'BAC'.
rv_points = 20.
WHEN 'VOC'.
rv_points = 10.
WHEN OTHERS.
rv_points = -1.
ENDCASE.
ENDMETHOD.
METHOD skill_points.
rv_points = ( iv_match * 30 + 50 ) DIV 100.
ENDMETHOD.
METHOD rating_for.
IF iv_score >= 75.
rv_rating = 'INVITE'.
ELSEIF iv_score >= 50.
rv_rating = 'REVIEW'.
ELSE.
rv_rating = 'REJECT'.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,33 @@
CLASS ltc_scorer DEFINITION FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS high_score FOR TESTING.
METHODS low_score FOR TESTING.
METHODS invalid_years FOR TESTING.
ENDCLASS.
CLASS ltc_scorer IMPLEMENTATION.
METHOD high_score.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate( iv_years = 5 iv_degree = 'PHD' iv_match = 100 ).
cl_abap_unit_assert=>assert_equals( exp = 'OK' act = ls_result-status ).
cl_abap_unit_assert=>assert_equals( exp = 100 act = ls_result-score ).
cl_abap_unit_assert=>assert_equals( exp = 'INVITE' act = ls_result-rating ).
ENDMETHOD.
METHOD low_score.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate( iv_years = 0 iv_degree = 'VOC' iv_match = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 10 act = ls_result-score ).
cl_abap_unit_assert=>assert_equals( exp = 'REJECT' act = ls_result-rating ).
ENDMETHOD.
METHOD invalid_years.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate( iv_years = -1 iv_degree = 'PHD' iv_match = 100 ).
cl_abap_unit_assert=>assert_equals( exp = 'YEAR' act = ls_result-status ).
cl_abap_unit_assert=>assert_initial( act = ls_result-rating ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,31 @@
FUNCTION {{p}}appl_score
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
EXPORTING
ev_score TYPE i
ev_rating TYPE string
EXCEPTIONS
invalid_years
invalid_match
invalid_degree.
DATA(lo_scorer) = NEW {{p}}app_scorer( ).
DATA(ls_result) = lo_scorer->evaluate(
iv_years = iv_years
iv_degree = iv_degree
iv_match = iv_match ).
IF ls_result-status = {{p}}app_scorer=>co_status-bad_years.
RAISE invalid_years.
ELSEIF ls_result-status = {{p}}app_scorer=>co_status-bad_match.
RAISE invalid_match.
ELSEIF ls_result-status = {{p}}app_scorer=>co_status-bad_degree.
RAISE invalid_degree.
ENDIF.
ev_score = ls_result-score.
ev_rating = ls_result-rating.
ENDFUNCTION.

View File

@@ -0,0 +1,61 @@
CLASS {{p}}t41_test DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS score_of
IMPORTING iv_years TYPE i iv_degree TYPE string iv_match TYPE i
RETURNING VALUE(rv_score) TYPE i.
METHODS invite_for_expert FOR TESTING.
METHODS review_for_graduate FOR TESTING.
METHODS reject_for_junior FOR TESTING.
METHODS invalid_input FOR TESTING.
ENDCLASS.
CLASS {{p}}t41_test IMPLEMENTATION.
METHOD score_of.
CALL FUNCTION '{{P}}APPL_SCORE'
EXPORTING
iv_years = iv_years
iv_degree = iv_degree
iv_match = iv_match
IMPORTING
ev_score = rv_score
EXCEPTIONS
invalid_years = 1
invalid_match = 2
invalid_degree = 3
OTHERS = 4.
cl_abap_unit_assert=>assert_subrc( exp = 0 ).
ENDMETHOD.
METHOD invite_for_expert.
cl_abap_unit_assert=>assert_equals(
exp = 100
act = score_of( iv_years = 5 iv_degree = 'PHD' iv_match = 100 ) ).
ENDMETHOD.
METHOD review_for_graduate.
cl_abap_unit_assert=>assert_equals(
exp = 50
act = score_of( iv_years = 5 iv_degree = 'VOC' iv_match = 0 ) ).
ENDMETHOD.
METHOD reject_for_junior.
cl_abap_unit_assert=>assert_equals(
exp = 18
act = score_of( iv_years = 1 iv_degree = 'VOC' iv_match = 0 ) ).
ENDMETHOD.
METHOD invalid_input.
CALL FUNCTION '{{P}}APPL_SCORE'
EXPORTING
iv_years = -1
iv_degree = 'PHD'
iv_match = 50
EXCEPTIONS
invalid_years = 1
OTHERS = 2.
cl_abap_unit_assert=>assert_equals( exp = 1 act = sy-subrc ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,15 @@
FUNCTION {{p}}appl_sample
IMPORTING
iv_years TYPE i
EXPORTING
ev_note TYPE string
EXCEPTIONS
invalid_years.
IF iv_years < 0.
RAISE invalid_years.
ENDIF.
ev_note = |{ iv_years } years of experience|.
ENDFUNCTION.

View File

@@ -0,0 +1,105 @@
# 1. Goal
A recruitment agency scores job applicants. A recruitment program calls one
function module for each applicant. The function module returns a score and a
recommendation.
The score calculation is pure logic. Put this logic in a new global class. The
function module calls this class. Do not put the calculation in the function
module.
# 2. Open questions
None.
# 3. Context
- Function group {{P}}FG_HR exists in package $TMP.
- Function module {{P}}APPL_SAMPLE exists in this group. It shows the
parameter style of the group.
- Create all new objects in package $TMP.
# 4. Contract
## 4.1 Function module {{P}}APPL_SCORE
Create the function module {{P}}APPL_SCORE in function group {{P}}FG_HR.
Use this interface:
```
FUNCTION {{p}}appl_score
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
EXPORTING
ev_score TYPE i
ev_rating TYPE string
EXCEPTIONS
invalid_years
invalid_match
invalid_degree.
```
## 4.2 Class {{P}}APP_SCORER
Create the class {{P}}APP_SCORER. The class is public and final. The class has
a public constructor without parameters.
Public type TY_RESULT has these components:
| Component | Type | Meaning |
|-----------|-----------|---------------------------|
| STATUS | TY_STATUS | Result of the input check |
| SCORE | i | Score from 0 to 100 |
| RATING | string | Recommendation |
TY_STATUS is a character type of length 4. The values of STATUS are 'OK',
'YEAR', 'MATC' and 'DEGR'.
Public method EVALUATE:
```
METHODS evaluate
IMPORTING
iv_years TYPE i
iv_degree TYPE string
iv_match TYPE i
RETURNING
VALUE(rs_result) TYPE ty_result.
```
The method does not raise an exception.
# 5. Business rules
1. Input check. Use this order:
1. If IV_YEARS is less than 0, STATUS is 'YEAR'.
2. Else if IV_MATCH is less than 0 or greater than 100, STATUS is 'MATC'.
3. Else if IV_DEGREE is not 'PHD', 'MAS', 'BAC' or 'VOC', STATUS is 'DEGR'.
4. Else STATUS is 'OK'.
2. If STATUS is not 'OK', SCORE is 0 and RATING is empty.
3. Experience points: 8 points for each full year of experience. The maximum
is 40 points.
4. Education points: 'PHD' gives 30 points, 'MAS' 25 points, 'BAC' 20 points
and 'VOC' 10 points.
5. Skill points: IV_MATCH percent of 30 points. Round the result half up to a
whole number.
6. SCORE is the sum of the experience points, the education points and the
skill points.
7. RATING depends on SCORE:
- SCORE 75 or more: 'INVITE'
- SCORE 50 to 74: 'REVIEW'
- SCORE less than 50: 'REJECT'
8. The function module raises the exception that belongs to STATUS:
- 'YEAR' raises INVALID_YEARS
- 'MATC' raises INVALID_MATCH
- 'DEGR' raises INVALID_DEGREE
For STATUS 'OK' the function module raises no exception. It exports SCORE
and RATING.
# 6. Constraints
- Release target: ABAP Platform 2025 (SAP_BASIS 816).
- Coding standard: Clean ABAP. Each method has less than 40 statements.
- No ATC finding of priority 1 or 2.
- Out of scope: do not change {{P}}APPL_SAMPLE.
# 7. Acceptance
- {{P}}APPL_SCORE and {{P}}APP_SCORER are active and have no syntax error.
- The hidden tests pass.
- Write ABAP Unit tests for the class in local test classes of the class.
- Write ABAP Unit tests for the function module in a global test class.

View File

@@ -0,0 +1,95 @@
{
"id": "G0106",
"category": "A",
"object_type": "FUNC",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 40,
"max_activations": 10
},
"seed": [
{
"type": "FUGR",
"name": "{{P}}FG_HR",
"description": "Recruitment function group"
},
{
"type": "FUNC",
"name": "{{P}}APPL_SAMPLE",
"functionGroup": "{{P}}FG_HR",
"file": "seed/appl_sample.func.abap",
"description": "Sample applicant module"
}
],
"contract": [
{
"type": "FUNC",
"name": "{{P}}APPL_SCORE",
"functionGroup": "{{P}}FG_HR",
"params": [
{
"name": "iv_years",
"type": "i"
},
{
"name": "iv_degree",
"type": "string"
},
{
"name": "iv_match",
"type": "i"
},
{
"name": "ev_score",
"type": "i"
},
{
"name": "ev_rating",
"type": "string"
}
]
},
{
"type": "CLAS",
"name": "{{P}}APP_SCORER"
}
],
"out_of_scope": [
"{{P}}APPL_SAMPLE"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T41_HIDDEN",
"file": "hidden/t41_hidden.clas.abap",
"description": "T41 hidden tests"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}APP_SCORER",
"file": "reference/app_scorer.clas.abap",
"testclasses_file": "reference/app_scorer.clas.testclasses.abap",
"description": "Applicant scoring logic"
},
{
"type": "FUNC",
"name": "{{P}}APPL_SCORE",
"functionGroup": "{{P}}FG_HR",
"file": "reference/appl_score.func.abap",
"description": "Applicant score module"
},
{
"type": "CLAS",
"name": "{{P}}T41_TEST",
"file": "reference/t41_test.clas.abap",
"description": "T41 own tests"
}
],
"craft_checks": [
"method_length"
]
}