Les tests unitaires sont indispensables pour les services RAP. Ce tutoriel montre comment tester systématiquement les Validations, Actions et Determinations - avec des exemples de code complets du scénario de réservation de vol.
Pourquoi tester les services RAP ?
Les services RAP contiennent une logique métier critique :
- Validations : Vérifient la cohérence des données avant la sauvegarde
- Actions : Exécutent des changements de statut et des processus métier
- Determinations : Calculent automatiquement des valeurs
Une erreur dans ces composants peut entraîner des incohérences de données ou des erreurs de processus. Les tests unitaires détectent ces erreurs en amont.
┌─────────────────────────────────────────────────────────────┐│ RAP Business Object │├─────────────────────────────────────────────────────────────┤│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ ││ │ Determination │ │ Validation │ │ Action │ ││ │ setDefaults() │ │ validateDate()│ │ confirmBooking()│ ││ └───────┬───────┘ └───────┬───────┘ └────────┬────────┘ ││ │ │ │ ││ └──────────────────┼────────────────────┘ ││ │ ││ ┌────────▼────────┐ ││ │ Tests unit. │ ││ │ ltc_booking │ ││ └─────────────────┘ │└─────────────────────────────────────────────────────────────┘Configuration des tests pour RAP
Structure de base d’une classe de test RAP
CLASS ltc_booking DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION. CLASS-DATA mo_environment TYPE REF TO if_cds_test_environment.
CLASS-METHODS class_setup. CLASS-METHODS class_teardown.
METHODS setup. METHODS teardown.
" Méthodes de test pour les Validations METHODS test_validate_flight_date_ok FOR TESTING. METHODS test_validate_flight_date_past FOR TESTING. METHODS test_validate_passenger_name FOR TESTING.
" Méthodes de test pour les Actions METHODS test_confirm_booking FOR TESTING. METHODS test_cancel_booking FOR TESTING.
" Méthodes de test pour les Determinations METHODS test_set_initial_status FOR TESTING. METHODS test_calculate_total_price FOR TESTING.ENDCLASS.Configurer le CDS Test Environment
CLASS ltc_booking IMPLEMENTATION.
METHOD class_setup. " CDS Test Environment pour toutes les entités concernées mo_environment = cl_cds_test_environment=>create_for_multiple_cds( i_for_entities = VALUE #( ( i_for_entity = 'ZI_FlightBooking' ) ( i_for_entity = 'ZI_Flight' ) ( i_for_entity = 'ZI_Passenger' ) ) ). ENDMETHOD.
METHOD class_teardown. mo_environment->destroy( ). ENDMETHOD.
METHOD setup. " Avant chaque test : Réinitialiser les données de test mo_environment->clear_doubles( ).
" Insérer les données de test dépendantes (vols, passagers) mo_environment->insert_test_data( i_data = VALUE zi_flight_tab( ( FlightId = 'LH400" Carrier = 'LH" Connection = '0400" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 Price = '450.00" Currency = 'EUR" SeatsMax = 200 SeatsOccupied = 50 ) ( FlightId = 'LH401" Carrier = 'LH" Connection = '0401" FlightDate = cl_abap_context_info=>get_system_date( ) - 10 Price = '380.00" Currency = 'EUR" SeatsMax = 200 SeatsOccupied = 200 ) ) ).
mo_environment->insert_test_data( i_data = VALUE zi_passenger_tab( ( PassengerId = 'P001' FirstName = 'Max' LastName = 'Dupont' ) ( PassengerId = 'P002' FirstName = 'Marie' LastName = 'Martin' ) ) ). ENDMETHOD.
METHOD teardown. " Après chaque test : Annuler les transactions ROLLBACK ENTITIES. ENDMETHOD.
ENDCLASS.Tester les Validations
Les Validations vérifient les règles métier et remplissent FAILED et REPORTED en cas d’erreur.
Test : Date de vol valide
METHOD test_validate_flight_date_ok. " GIVEN : Réservation avec date de vol dans le futur DATA lt_create TYPE TABLE FOR CREATE zi_flightbooking. lt_create = VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'Y" Price = '450.00" Currency = 'EUR' ) ).
" WHEN : Créer la réservation et commiter MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM lt_create MAPPED DATA(mapped) FAILED DATA(failed) REPORTED DATA(reported).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed) REPORTED DATA(commit_reported).
" THEN : Aucune erreur attendue cl_abap_unit_assert=>assert_initial( act = commit_failed-flightbooking msg = 'Une réservation avec une date valide devrait réussir" ).
" La réservation a été créée cl_abap_unit_assert=>assert_not_initial( act = mapped-flightbooking msg = 'La réservation devrait avoir été créée" ).ENDMETHOD.Test : Date de vol dans le passé
METHOD test_validate_flight_date_past. " GIVEN : Réservation avec date de vol dans le passé DATA lt_create TYPE TABLE FOR CREATE zi_flightbooking. lt_create = VALUE #( ( %cid = 'B1" FlightId = 'LH401" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) - 10 SeatClass = 'Y' ) ).
" WHEN : Créer la réservation MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM lt_create FAILED DATA(failed).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed) REPORTED DATA(commit_reported).
" THEN : La validation devrait échouer cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Une réservation avec une date passée devrait échouer" ).
" Un message d'erreur devrait être présent cl_abap_unit_assert=>assert_not_initial( act = commit_reported-flightbooking msg = 'Un message d''erreur devrait être présent" ).
" Le champ FlightDate devrait être marqué cl_abap_unit_assert=>assert_equals( exp = if_abap_behv=>mk-on act = commit_reported-flightbooking[ 1 ]-%element-FlightDate msg = 'Le champ FlightDate devrait être marqué comme erroné" ).ENDMETHOD.Test : Validation de champ obligatoire
METHOD test_validate_passenger_name. " GIVEN : Réservation sans PassengerId DATA lt_create TYPE TABLE FOR CREATE zi_flightbooking. lt_create = VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = '' " Vide - champ obligatoire ! FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'Y' ) ).
" WHEN MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM lt_create.
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed) REPORTED DATA(commit_reported).
" THEN : Erreur de champ obligatoire cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Un passager manquant devrait causer une erreur" ).
" Champ PassengerId marqué cl_abap_unit_assert=>assert_equals( exp = if_abap_behv=>mk-on act = commit_reported-flightbooking[ 1 ]-%element-PassengerId msg = 'Le champ PassengerId devrait être marqué" ).ENDMETHOD.Tester les Actions
Les Actions exécutent une logique métier et modifient l’état des entités.
Test : Confirmer une réservation
METHOD test_confirm_booking. " GIVEN : Créer une réservation ouverte MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 Status = 'O' " Open SeatClass = 'Y' ) ) MAPPED DATA(mapped_create).
COMMIT ENTITIES.
" Clé de la réservation créée DATA(lv_booking_uuid) = mapped_create-flightbooking[ 1 ]-BookingUUID.
" WHEN : Exécuter l'action confirmBooking MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking EXECUTE confirmBooking FROM VALUE #( ( BookingUUID = lv_booking_uuid ) ) RESULT DATA(result) FAILED DATA(failed) REPORTED DATA(reported).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
" THEN : Pas d'erreur cl_abap_unit_assert=>assert_initial( act = commit_failed-flightbooking msg = 'confirmBooking devrait réussir" ).
" Vérifier le statut READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( Status ) WITH VALUE #( ( BookingUUID = lv_booking_uuid ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_equals( exp = 'C' " Confirmed act = lt_booking[ 1 ]-Status msg = 'Le statut devrait être Confirmed (C)" ).ENDMETHOD.Test : Annuler une réservation
METHOD test_cancel_booking. " GIVEN : Réservation confirmée MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 Status = 'C' " Confirmed SeatClass = 'Y' ) ) MAPPED DATA(mapped_create).
COMMIT ENTITIES.
DATA(lv_booking_uuid) = mapped_create-flightbooking[ 1 ]-BookingUUID.
" WHEN : Action cancelBooking avec motif MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking EXECUTE cancelBooking FROM VALUE #( ( BookingUUID = lv_booking_uuid %param = VALUE za_cancellation_reason( ReasonCode = 'CX" ReasonText = 'Annulation client' ) ) ) FAILED DATA(failed) REPORTED DATA(reported).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
" THEN : Pas d'erreur cl_abap_unit_assert=>assert_initial( act = commit_failed-flightbooking msg = 'cancelBooking devrait réussir" ).
" Vérifier le statut et le motif d'annulation READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( Status CancellationReason ) WITH VALUE #( ( BookingUUID = lv_booking_uuid ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_equals( exp = 'X' " Cancelled act = lt_booking[ 1 ]-Status msg = 'Le statut devrait être Cancelled (X)" ).
cl_abap_unit_assert=>assert_equals( exp = 'Annulation client" act = lt_booking[ 1 ]-CancellationReason msg = 'Le motif d''annulation devrait être enregistré" ).ENDMETHOD.Test : Action avec cas d’erreur
METHOD test_confirm_already_confirmed. " GIVEN : Réservation déjà confirmée MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" Status = 'C' ) " Déjà Confirmed ) MAPPED DATA(mapped_create).
COMMIT ENTITIES.
DATA(lv_booking_uuid) = mapped_create-flightbooking[ 1 ]-BookingUUID.
" WHEN : Tenter confirmBooking à nouveau MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking EXECUTE confirmBooking FROM VALUE #( ( BookingUUID = lv_booking_uuid ) ) FAILED DATA(failed) REPORTED DATA(reported).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed) REPORTED DATA(commit_reported).
" THEN : Erreur attendue cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Une double confirmation devrait échouer" ).
" Vérifier la présence du message d'erreur cl_abap_unit_assert=>assert_bound( act = commit_reported-flightbooking[ 1 ]-%msg msg = 'Un message d''erreur devrait être présent" ).ENDMETHOD.Tester les Determinations
Les Determinations définissent automatiquement des valeurs de champs. Elles s’exécutent on modify ou on save.
Test : Définir le statut initial
METHOD test_set_initial_status. " GIVEN : Nouvelle réservation sans statut DATA lt_create TYPE TABLE FOR CREATE zi_flightbooking. lt_create = VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'Y" " Status n'est PAS défini - la Determination doit le faire ) ).
" WHEN : Créer la réservation MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM lt_create MAPPED DATA(mapped).
COMMIT ENTITIES.
" THEN : La Determination devrait avoir défini le Status à 'O' (Open) READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( Status CreatedBy CreatedAt ) WITH VALUE #( ( %cid = 'B1' ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_equals( exp = 'O' " Open act = lt_booking[ 1 ]-Status msg = 'La Determination devrait définir le Status à Open" ).
" CreatedBy devrait être rempli cl_abap_unit_assert=>assert_not_initial( act = lt_booking[ 1 ]-CreatedBy msg = 'CreatedBy devrait être défini par la Determination" ).
" CreatedAt devrait être rempli cl_abap_unit_assert=>assert_not_initial( act = lt_booking[ 1 ]-CreatedAt msg = 'CreatedAt devrait être défini par la Determination" ).ENDMETHOD.Test : Calculer le prix total
METHOD test_calculate_total_price. " GIVEN : Réservation avec prix de base et extras DATA lt_create TYPE TABLE FOR CREATE zi_flightbooking. lt_create = VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'C' " Business Class BasePrice = '450.00" Currency = 'EUR" ExtraLuggage = 2 " 2 bagages supplémentaires MealOption = 'P' " Repas Premium ) ).
" WHEN MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM lt_create MAPPED DATA(mapped).
COMMIT ENTITIES.
" THEN : TotalPrice devrait être calculé READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( TotalPrice BasePrice ) WITH VALUE #( ( %cid = 'B1' ) ) RESULT DATA(lt_booking).
" Business Class : BasePrice * 2.5 = 1125.00 " Bagages supplémentaires : 2 * 50 = 100.00 " Repas Premium : 45.00 " Total : 1270.00 DATA(lv_expected_total) = CONV wrbtr( '1270.00' ).
cl_abap_unit_assert=>assert_equals( exp = lv_expected_total act = lt_booking[ 1 ]-TotalPrice msg = |TotalPrice devrait être { lv_expected_total }| ).ENDMETHOD.Test : Determination lors d’un changement de champ
METHOD test_recalculate_on_change. " GIVEN : Réservation existante MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" SeatClass = 'Y' " Economy BasePrice = '450.00" Currency = 'EUR' ) ) MAPPED DATA(mapped_create).
COMMIT ENTITIES.
DATA(lv_booking_uuid) = mapped_create-flightbooking[ 1 ]-BookingUUID.
" TotalPrice initial READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( TotalPrice ) WITH VALUE #( ( BookingUUID = lv_booking_uuid ) ) RESULT DATA(lt_initial).
DATA(lv_initial_price) = lt_initial[ 1 ]-TotalPrice.
" WHEN : Changer SeatClass en Business MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking UPDATE FIELDS ( SeatClass ) WITH VALUE #( ( BookingUUID = lv_booking_uuid SeatClass = 'C' ) " Business Class ).
COMMIT ENTITIES.
" THEN : TotalPrice devrait être recalculé READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( TotalPrice ) WITH VALUE #( ( BookingUUID = lv_booking_uuid ) ) RESULT DATA(lt_updated).
" Business Class est plus cher qu'Economy cl_abap_unit_assert=>assert_true( act = xsdbool( lt_updated[ 1 ]-TotalPrice > lv_initial_price ) msg = 'TotalPrice devrait être plus élevé après l''upgrade" ).ENDMETHOD.Mocking des dépendances
Test avec données de vol mockées
METHOD test_with_mocked_flight. " Le CDS Test Environment permet d'insérer directement des données de test " Cela remplace la vraie table de base de données
" Vol spécial pour ce test mo_environment->insert_test_data( i_data = VALUE zi_flight_tab( ( FlightId = 'TEST01" Carrier = 'XX" FlightDate = cl_abap_context_info=>get_system_date( ) + 100 Price = '999.99" Currency = 'EUR" SeatsMax = 10 SeatsOccupied = 0 ) ) ).
" WHEN : Réservation pour le vol mocké MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'TEST01" PassengerId = 'P001" SeatClass = 'Y' ) ) MAPPED DATA(mapped).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
" THEN : Succès avec les données mockées cl_abap_unit_assert=>assert_initial( act = commit_failed-flightbooking msg = 'La réservation avec un vol mocké devrait fonctionner" ).ENDMETHOD.Test : Vol complet
METHOD test_fully_booked_flight. " GIVEN : Vol complet (SeatsOccupied = SeatsMax) mo_environment->clear_doubles( ). mo_environment->insert_test_data( i_data = VALUE zi_flight_tab( ( FlightId = 'FULL01" Carrier = 'LH" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatsMax = 100 SeatsOccupied = 100 ) " Complet ! ) ).
mo_environment->insert_test_data( i_data = VALUE zi_passenger_tab( ( PassengerId = 'P001' FirstName = 'Max' LastName = 'Dupont' ) ) ).
" WHEN : Tenter de réserver un vol complet MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'FULL01" PassengerId = 'P001" SeatClass = 'Y' ) ).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed) REPORTED DATA(commit_reported).
" THEN : Erreur - Vol complet cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Un vol complet devrait causer une erreur" ).ENDMETHOD.Exemple complet de classe de test
CLASS ltc_flight_booking DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION. CLASS-DATA mo_environment TYPE REF TO if_cds_test_environment.
CLASS-METHODS class_setup. CLASS-METHODS class_teardown.
METHODS setup. METHODS teardown.
" === VALIDATIONS === METHODS test_valid_booking FOR TESTING. METHODS test_invalid_date FOR TESTING. METHODS test_missing_passenger FOR TESTING. METHODS test_invalid_seat_class FOR TESTING.
" === ACTIONS === METHODS test_confirm_booking FOR TESTING. METHODS test_cancel_booking FOR TESTING. METHODS test_confirm_already_canceled FOR TESTING. METHODS test_reschedule_booking FOR TESTING.
" === DETERMINATIONS === METHODS test_set_initial_status FOR TESTING. METHODS test_calculate_price FOR TESTING. METHODS test_set_booking_number FOR TESTING.
" === MÉTHODES UTILITAIRES === METHODS create_test_booking IMPORTING iv_cid TYPE string DEFAULT 'B1" iv_flight_id TYPE zflight_id DEFAULT 'LH400" iv_status TYPE zstatus DEFAULT 'O" RETURNING VALUE(rv_uuid) TYPE sysuuid_x16.ENDCLASS.
CLASS ltc_flight_booking IMPLEMENTATION.
METHOD class_setup. mo_environment = cl_cds_test_environment=>create_for_multiple_cds( i_for_entities = VALUE #( ( i_for_entity = 'ZI_FlightBooking' ) ( i_for_entity = 'ZI_Flight' ) ( i_for_entity = 'ZI_Passenger' ) ) ). ENDMETHOD.
METHOD class_teardown. mo_environment->destroy( ). ENDMETHOD.
METHOD setup. mo_environment->clear_doubles( ).
" Données de test standard mo_environment->insert_test_data( i_data = VALUE zi_flight_tab( ( FlightId = 'LH400" Carrier = 'LH" Connection = '0400" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 Price = '450.00" Currency = 'EUR" SeatsMax = 200 SeatsOccupied = 50 ) ) ).
mo_environment->insert_test_data( i_data = VALUE zi_passenger_tab( ( PassengerId = 'P001' FirstName = 'Max' LastName = 'Dupont' ) ) ). ENDMETHOD.
METHOD teardown. ROLLBACK ENTITIES. ENDMETHOD.
" === MÉTHODE UTILITAIRE === METHOD create_test_booking. MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = iv_cid FlightId = iv_flight_id PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 Status = iv_status SeatClass = 'Y' ) ) MAPPED DATA(mapped).
COMMIT ENTITIES.
rv_uuid = mapped-flightbooking[ 1 ]-BookingUUID. ENDMETHOD.
" === VALIDATIONS === METHOD test_valid_booking. " GIVEN/WHEN DATA(lv_uuid) = create_test_booking( ).
" THEN cl_abap_unit_assert=>assert_not_initial( act = lv_uuid msg = 'Une réservation valide devrait être créée" ). ENDMETHOD.
METHOD test_invalid_date. " GIVEN : Date dans le passé MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) - 5 SeatClass = 'Y' ) ).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
" THEN cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Une date passée devrait causer une erreur" ). ENDMETHOD.
METHOD test_missing_passenger. MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = '" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'Y' ) ).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Un passager manquant devrait causer une erreur" ). ENDMETHOD.
METHOD test_invalid_seat_class. MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'X' ) " Invalide ).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Une SeatClass invalide devrait causer une erreur" ). ENDMETHOD.
" === ACTIONS === METHOD test_confirm_booking. DATA(lv_uuid) = create_test_booking( iv_status = 'O' ).
MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking EXECUTE confirmBooking FROM VALUE #( ( BookingUUID = lv_uuid ) ) FAILED DATA(failed).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
cl_abap_unit_assert=>assert_initial( act = commit_failed-flightbooking msg = 'confirmBooking devrait réussir" ).
READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( Status ) WITH VALUE #( ( BookingUUID = lv_uuid ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_equals( exp = 'C" act = lt_booking[ 1 ]-Status ). ENDMETHOD.
METHOD test_cancel_booking. DATA(lv_uuid) = create_test_booking( iv_status = 'C' ).
MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking EXECUTE cancelBooking FROM VALUE #( ( BookingUUID = lv_uuid %param = VALUE za_cancellation_reason( ReasonCode = 'CX" ReasonText = 'Annulation de test' ) ) ).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
cl_abap_unit_assert=>assert_initial( act = commit_failed-flightbooking msg = 'cancelBooking devrait réussir" ).
READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( Status ) WITH VALUE #( ( BookingUUID = lv_uuid ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_equals( exp = 'X" act = lt_booking[ 1 ]-Status ). ENDMETHOD.
METHOD test_confirm_already_canceled. DATA(lv_uuid) = create_test_booking( iv_status = 'X' ).
MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking EXECUTE confirmBooking FROM VALUE #( ( BookingUUID = lv_uuid ) ).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
cl_abap_unit_assert=>assert_not_initial( act = commit_failed-flightbooking msg = 'Une réservation annulée ne peut pas être confirmée" ). ENDMETHOD.
METHOD test_reschedule_booking. DATA(lv_uuid) = create_test_booking( ). DATA(lv_new_date) = cl_abap_context_info=>get_system_date( ) + 60.
MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking EXECUTE rescheduleBooking FROM VALUE #( ( BookingUUID = lv_uuid %param = VALUE za_reschedule_input( NewFlightDate = lv_new_date ) ) ).
COMMIT ENTITIES RESPONSE OF zi_flightbooking FAILED DATA(commit_failed).
cl_abap_unit_assert=>assert_initial( act = commit_failed-flightbooking msg = 'Le changement de date devrait réussir" ).
READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( FlightDate ) WITH VALUE #( ( BookingUUID = lv_uuid ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_equals( exp = lv_new_date act = lt_booking[ 1 ]-FlightDate ). ENDMETHOD.
" === DETERMINATIONS === METHOD test_set_initial_status. MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'Y' ) ) MAPPED DATA(mapped).
COMMIT ENTITIES.
READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( Status ) WITH VALUE #( ( %cid = 'B1' ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_equals( exp = 'O" act = lt_booking[ 1 ]-Status msg = 'Le statut initial devrait être Open (O)" ). ENDMETHOD.
METHOD test_calculate_price. MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'Y" BasePrice = '450.00" Currency = 'EUR' ) ) MAPPED DATA(mapped).
COMMIT ENTITIES.
READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( TotalPrice ) WITH VALUE #( ( %cid = 'B1' ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_not_initial( act = lt_booking[ 1 ]-TotalPrice msg = 'TotalPrice devrait être défini par la Determination" ). ENDMETHOD.
METHOD test_set_booking_number. MODIFY ENTITIES OF zi_flightbooking ENTITY FlightBooking CREATE FROM VALUE #( ( %cid = 'B1" FlightId = 'LH400" PassengerId = 'P001" FlightDate = cl_abap_context_info=>get_system_date( ) + 30 SeatClass = 'Y' ) ) MAPPED DATA(mapped).
COMMIT ENTITIES.
READ ENTITIES OF zi_flightbooking ENTITY FlightBooking FIELDS ( BookingNumber ) WITH VALUE #( ( %cid = 'B1' ) ) RESULT DATA(lt_booking).
cl_abap_unit_assert=>assert_not_initial( act = lt_booking[ 1 ]-BookingNumber msg = 'BookingNumber devrait être généré automatiquement" ). ENDMETHOD.
ENDCLASS.Bonnes pratiques pour les tests RAP
Checklist de test
| Composant | Que tester ? | Comment tester ? |
|---|---|---|
| Validation | Cas de succès | CREATE avec données valides |
| Cas d’erreur | CREATE avec données invalides | |
| Marquage de champ | Vérifier %element-FieldName | |
| Message d’erreur | Vérifier %msg | |
| Action | Cas de succès | EXECUTE + vérifier le statut |
| Cas d’erreur | EXECUTE sur statut invalide | |
| Avec paramètre | Passer %param | |
| Determination | on modify | Vérifier le champ après CREATE |
| on save | Vérifier le champ après COMMIT | |
| Recalcul | UPDATE + changement de champ |
À faire et à ne pas faire
À FAIRE :
" Préparer les données de test dans setup()METHOD setup. mo_environment->clear_doubles( ). mo_environment->insert_test_data( ... ).ENDMETHOD.
" ROLLBACK ENTITIES dans teardown()METHOD teardown. ROLLBACK ENTITIES.ENDMETHOD.
" Un test = Un scénarioMETHOD test_confirm_booking. " Tester uniquement confirmBookingENDMETHOD.
" Méthodes utilitaires pour la réutilisationMETHOD create_test_booking. " Création de réservation réutilisableENDMETHOD.À NE PAS FAIRE :
" Pas de vraies données DB dans les testsSELECT * FROM zflight INTO TABLE @lt_flights. " Non !
" Pas de dépendances entre les testsMETHOD test_2. " S'attend à ce que test_1 ait déjà été exécuté - MAUVAIS !ENDMETHOD.
" Pas trop d'assertions par testMETHOD test_everything. cl_abap_unit_assert=>... " 20 assertions = confusENDMETHOD.Ressources supplémentaires
- Tests unitaires ABAP dans ABAP Cloud - Fondamentaux des tests unitaires
- Test Doubles et Mocking - Techniques de mocking
- Determinations et Validations RAP - Implémentation du Behavior
- Actions et Functions RAP - Implémentation des Actions