How we do multicase tests
This how-to describes our approach in doing multi-case unit tests with help of Abap mockup loader.
Let's suppose we have a method which is designed to identify quality of a product. We input a table of quality inspection parameters and expect some quality class assessment, in the example "A" or "B". Certain parameters are compulsory and must not be skipped during quality inspection. Thus, if they are missing the method raises an exception.
You want to arrange the test infrastructure so that it is easy to add new tests (in particular, no coding required). Here is how we do it.
Let's say we prepared a unit test table with 3 cases, one of which has a missing parameter.
DOCNO PARAM VALUE
10 QUANTITY 99
10 MOISTURE 12,6
20 WEIGHT 14,89
20 QUANTITY 103
20 MOISTURE 11,9
30 WEIGHT 14,89
30 QUANTITY <<< Missing quantity
30 MOISTURE 12,10
Another table is the index of test cases. Each refers to a DOCNO
, describes expected result and describes the case in a human-readable form. TYPE
field describes if the case is positive or negative.
TESTID TYPE DOCNO EXPECT MSG
1 + 10 A Case with quality A
2 + 11 B Case with quality B
3 - 12 Case with a missing Param
- Define the test case index structure (in the test class)
public section.
types:
begin of ty_test_case,
testid type i,
type type char2,
docno type char10,
expect type char1,
msg type string,
end of ty_test_case.
data at_cases type table of ty_test_case.
data o_ml type ref to zcl_mockup_loader.
data o type ref to zcl_class_under_test.
- In
setup()
method acquire a mockup loader instance and load index (see How to load mockups forclass_setup()
tips)
method setup.
data lo_ex type ref to cx_static_check.
create object o importing ... " << Object under test initialization
try.
o_ml = zcl_mockup_loader=>get_instance( ).
o_ml->load_data(
exporting i_obj = 'TEST1/index' " << we placed here index file
importing e_container = me->at_cases ).
catch cx_static_check into lo_ex.
fail( lo_ex->get_text( ) ). " << we inherit test classes from cl_aunit_assert
endtry.
endmethod.
- And here is main test cycle
method test_assess_quality.
data l_case type ty_test_case.
data lo_ex type cx_root.
data lt_insp type zcl_class_under_test=>ty_inspections. " Whatever your type is
data l_act type zcl_class_under_test=>ty_quality. " Whatever your type is
loop at at_cases into l_case. " Loop through test cases
clear lo_ex.
try.
o_ml->load_data(
exporting i_obj = 'TEST1/inspections' " Ispections data file
i_where = 'DOCNO = ' && l_case-testid " Filter relevant lines
importing e_container = lt_insp ).
l_act = o->assess_quality( lt_insp ).
catch cx_static_check into lo_ex.
fail( lo_ex->get_text( ) ). " Mockup load error handling just in case
catch cx_root into lo_ex.
" do nothing - this is the expected exception for negative tests
" better use specific exeption classes of course
endtry.
if l_case-type = '+'. " Positive test
" msg indicates the failed test id and it's description
assert_initial( act = lo_ex msg = |[{ l_case-testid }] { l_case-msg }| ).
assert_equals( act = l_act
exp = l_case-expect
msg = |[{ l_case-testid }] { l_case-msg }| ).
else. " '-' " Negative test
assert_not_initial( act = lo_ex msg = |[{ l_case-testid }] { l_case-msg }| ).
" Potentially more specific error check code should follow
endif.
endloop.
endmethod.
- That's all ! :)
Now you've got an easy extendable test infrustructure. New test cases of the same instance can be added without extra coding. See also How to simplify test data creation with Excel and EXCEL2TXT vbscript on how to make test preparation more convenient.