Database preparation for unit testing made simple. Store snapshots (bundles) of your database records for later use in unit tests.
The snapshots should avoid breaking unit tests after system copies and
other database manipulations. This is achieved by providing a wrapper
for the OpenSQL replacement service in class cl_osql_replace
, that
makes huge setups unnecessary.
Replace this huge setup method
METHOD setup.
DATA: airlines TYPE STANDARD TABLE OF zcarr_fake,
replaced_tables TYPE cl_osql_replace=>tt_replacement.
DELETE FROM airlines.
airlines = VALUE #(
( carrid = 'TG' carrname = 'Thai Airways' )
).
INSERT zcarr_fake FROM airlines.
replaced_tables = VALUE #(
( source = 'SCARR' target = 'ZCARR_FAKE' )
).
cl_osql_replace=>activate_replacement( EXPORTING
replacement_table = replaced_tables ).
ENDMETHOD.
by just two method calls:
METHOD setup.
DATA(db_preparator) = NEW zimport_bundle_from_tdc( tdc = 'ZAIRLINES'
tdc_version = 1 variant = 'ECATTDEFAULT' ).
db_preparator->replace_content_completly( ).
db_preparator->activate_osql_replacement( ).
ENDMETHOD.
Bundles are stored either in an ECATT test data container or in a cluster (binary MIME-object in transaction smw0).
In the first step we can choose the database records,
which should be exported into the bundle.
The OpenSQL replacement service needs a so called fake table with the same
structure as the original table. From this fake table the database records are
read or they are written back in this fake table. In the export step we link
original and fake table as shown in the picture below.
Figure 1 Export step for table scarr in program zexport_gui
In figure 1 the original table is named scarr
, the fake table zcarr_fake
.
Fake tables can be left empty, if the OpenSQL replacement service isn't installed.
The SQL where restriction can be prefixed a FOR ALL ENTRIES IN
, which acts
like the corresponding ABAP-statement. As internal table any original table from the bundle can be given. Internal table name should be 'X' && table_name
. E.g.
Database table | Fake database table | SQL where restriction |
---|---|---|
SCARR | ZCARR_FAKE | carrid in ('TG', 'AA') |
SPFLI | ZSPFLI_FAKE | FOR ALL ENTRIES IN xzcarr_fake WHERE carrid = xzcarr_fake-carrid |
Joins can be expressed with subqueries. Let's consider the following join:
SELECT * FROM sflight AS f INNER JOIN spfli AS p
ON p~carrid = f~carrid AND p~connid = f~connid
WHERE p~airpto = 'BKK' AND f~fldate = '20210420'.
The database records can be picked up in programm zexport_gui
with subqueries:
Database table | Fake database table | SQL where restriction |
---|---|---|
SFLIGHT | ZCARR_SFLIGHT | fldate = '20210420' AND EXISTS ( SELECT * FROM spfli WHERE carrid = sflight |
SPFLI | ZCARR_SPFLI | FOR ALL ENTRIES IN xsflight WHERE carrid = xsflight-carrid AND connid = xsflight-connid |
In the ABAP unit-testclass the database records exported in previous step
can be imported in the fake tables or in the original tables,
if the corresponding fake table was left empty.
The API for the import step is located in class zimport_bundle_from_cluster
for clusters or in class zimport_bundle_from_tdc
for
ECATT test data container.
For testing Rfc-Client- or Rfc-Serverprograms or programs,
which interact through the JSON Adapter for ABAP Function Modules
a API is located in function-group zimport_bundle
.
A example can be found in the listing below.
CLASS test_airlines DEFINITION FOR TESTING DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
" activate replacement service
METHODS setup.
METHODS thai_should_be_found FOR TESTING.
ENDCLASS.
CLASS test_airlines IMPLEMENTATION.
METHOD setup.
DATA(db_preparator) = NEW zimport_bundle_from_tdc( tdc = 'ZAIRLINES'
tdc_version = 1 variant = 'ECATTDEFAULT' ).
db_preparator->replace_content_completly( ).
db_preparator->activate_osql_replacement( ).
ENDMETHOD.
METHOD thai_should_be_found.
DATA: exp_airlines TYPE STANDARD TABLE OF scarr.
exp_airlines = VALUE #( ( carrid = 'TG' carrname = 'Thai airways'
currcode = 'THB' url = 'https://thaiairways.com' ) ).
SELECT * FROM scarr INTO TABLE @DATA(act_airlines).
cl_abap_unit_assert=>assert_equals( exp = exp_airlines
act = act_airlines ).
ENDMETHOD.
ENDCLASS.
The APIs in class zimport_bundle_from_cluster
or
in class zimport_bundle_from_tdc
can only be used in
development systems, where
dangerous ABAP unit-testclasses are enabled.
Content of fake tables listed in the whitelist can be completely
overriden. The whitelist is maintained in parameter
ZIMPORT_REPLACE_WHITELIST
(transaction stvarv
, table tvarvc
).
- Bundle: a collection of database records, which are stored outside of the database tables.
- Cluster: a MIME-object in transaction
smw0
, which contains the bundle - TDC: abbreviation for ECATT test data container
Cloning can be done with abapGit. The code is backwards compatible until release 7.40. The replacement services need higher releases (SAP NetWeaver 7.51 or 7.52).