Professional Documents
Culture Documents
FM
ALSM_EXCEL_TO_INTERNAL_TABLE is useful but has few limitation.
FM ALSM_EXCEL_TO_INTERNAL_TABLE can only load up to 9999 rows from Excel file. This
simple utility class would overcome this limitation.
Utility class to Upload Excel file
*
CLASS lcl_excel_uploader DEFINITION.
PUBLIC SECTION.
DATA: header_rows_count TYPE i.
DATA: max_rows TYPE i.
DATA: filename TYPE localfile.
METHODS:
constructor.
METHODS:
upload CHANGING ct_data TYPE ANY TABLE.
PRIVATE SECTION.
DATA: lv_tot_components TYPE i.
METHODS:
do_upload
IMPORTING
iv_begin TYPE i
iv_end TYPE i
EXPORTING
rv_empty TYPE flag
CHANGING
ct_data TYPE STANDARD TABLE.
*
CLASS lcl_excel_uploader IMPLEMENTATION.
METHOD constructor.
max_rows = 9999.
ENDMETHOD. "constructor
METHOD upload.
DATA: lo_struct TYPE REF TO cl_abap_structdescr,
lo_table TYPE REF TO cl_abap_tabledescr,
lt_comp TYPE cl_abap_structdescr=>component_table.
ENDMETHOD. "do_upload
ENDCLASS. "lcl_excel_uploader IMPLEMENTATION
*
TYPES:
BEGIN OF ty_data,
f1 TYPE char10,
f2 TYPE char12,
f3 TYPE matnr,
END OF ty_data.
TYPES: tt_data TYPE STANDARD TABLE OF ty_data.
DATA: t_data TYPE tt_data.
*
START-OF-SELECTION.
DATA: lo_uploader TYPE REF TO lcl_excel_uploader.
CREATE OBJECT lo_uploader.
lo_uploader->max_rows = 10.
lo_uploader->filename = 'C:temp123.xls'.
lo_uploader->header_rows_count = 1.
lo_uploader->upload( CHANGING ct_data = t_data ).
By Naimesh Patel | April 22, 2013 | ABAP Objects, ABAP Unit Test | 4,968 | 0
Lets check few basics of Test Driven Development as well as for ABAP Unit.
1 Preface
2 What is TDD?
3 Why to Write a Test First?
4 Test Properties
4.1
4.2
5 Client Based Configuration
6 FOR TESTING Keyword
7 Class CL_AUNIT_ASSERT
8 Next Article
Preface
In this article, I would try to explain few basics of the ABAP Unit. In this
series, I’m planning for these articles:
What is TDD?
Test Driven Development is a process in which you rely on test to validate the
functionality of the production code. In this process, tests are written first,
then the actual production code to pass the tests. This test would be a separate
code than the production methods. The production methods are also knows as Method
Under Test and the class where production code is known as Class Under Test.
To develop the applications using TDD technique, we must have an automated Unit
Test mechanism available in the programming language. With an introduction of the
ABAP Unit framework in SAP from the ABAP release 6.20, it is now possible to use
TDD technique in application development.
When working with TDD, you first write a empty code block (a shell) which would
finally carry your Production Code. After that you write a test to validate the
functionality with using Actual and Expected. After that you re-factor your
production code to pass your test. At high level the process of TDD is a Cycle.
Your code would go through many iterations of writing test, refactoring production
code, and test execution.
Write a Test
Make Test Pass
Refactoring
So you would think why to write a test first. When you start writing the test, you
would start thinking of various aspects of requirement and start designing the
production methods accordingly – Like defining the Attributes or parameters to the
method. You would also think on the expected results based on the inputs e.g. If I
pass x value, I would get x/2 which is my expected value. If you actual method is
to Sum of the value as shown in the first article, you would know what is the
expected value out of the method when you pass the inputs.
Test Properties
As you would have noticed in the example in first post, that I have used #AU
followed by the text. These are test properties – Risk Level and Duration.
Risk Level defines the risk of the test. When executing the test, system would
check the risk level against predefined risk level in the Client settings. If your
test has a higher risk level, ABAP Unit framework would ignore that test and will
not execute that test. You can specify one of these three possible values:
Harmless – The execution of this test doesn’t affect any existing processes or
Database. This is default setting.
Dangerous (Alarming) – This type of test makes changes to DB or persistent
Data.
Critical – This type of test would make changes to Customization as well as the
Persistent data. A careful look is required.
Duration – Similar to Risk level, all the test would need to have expected runtime
duration. ABAP Unit framework will not execute the tests with higher duration than
defined in the client level configuration. For Duration, you specify these values:
Short – Gets executed very fast. This is default setting at the client
settings. Generally < 1 minute
Medium – Gets executed in a bit. Little bit extra time than the short duration.
In the range of 1 minute to 10 minutes
Long – takes a while to process the test. The execution time would be more than
10 minutes
You can maintain the client based configuration for switch off Unit Test, allowed
preference for Risk level and Duration in the transaction SAUNIT_CLIENT_SETUP. You
must not change the settings on the fly as all of your tests may become non-
executable because they are having different Risk Level and Duration than defined
in the settings. Setting screen looks similar to this:
ABAP Unit Client Customization
FOR TESTING Keyword
The addition Testing is important when defining the test class. If you omit the
addition, your class would be considered as a simple production class. The FOR
TESTING addition makes it a test class. You would also need at least one method
with addition FOR TESTING.
Class CL_AUNIT_ASSERT
Class CL_AUNIT_ASSERT has various methods to test various different scenarios. Most
used method is ASSERT_EQUALS. This method takes Actual and Expected values as an
argument and tells the Unit Framework if the tests is passed or failed. Over the
next various articles, I would leverage few of the methods from the class to
validate the test.
Next Article
In the next article, I would cover Test Fixture methods. Stay tuned!
By Naimesh Patel | May 1, 2013 | ABAP Objects, ABAP Unit Test | 4,632 | 0
In the series of ABAP Unit, lets check out the Test Fixture methods.
Preface
In this article, I would cover various different methods for test fixture. In this
series, I’m planning for these articles:
Test fixture is the test configuration like test data or test objects. This data
would be used within the test methods. Fixture would be executed before the actual
test method gets executed. So when the test is getting performed, the test data or
test objects setup in fixture method can be used.
In ABAP, the test fixture is achieved using these predefined methods. These method
would be called automatically by ABAP framework if they exist in the test class.
SETUP – Instance method SETUP would be called before each test within the test
class
TEARDOWN – In contrary to SETUP, instance method TEARDOWN would be called after
each test within the test class
CLASS_SETUP – Similar to SETUP, static method CLASS_SETUP would be used to set
up the data once before the first test in the class gets executed
CLASS_TEARDOWN – Like TEARDOWN, static method TEARDOWN would be used to clear
the data once after the last test in the class gets executed
Method SETUP( )
Special method SETUP( ) is used to setup the common test data for the same test
methods of the same test class or of the inherited test class. This method would be
called before calling the test method by the ABAP Unit framework. So, basically it
would be called as many times as many test methods are there in a single test
class.
In this method, you should generally setup your test data which can be leveraged by
various different test within the same test class. Simple example, would be to
setup default value for a variable, or instantiate the object for Production code.
Method TEARDOWN( )
Special method TEARDOWN( ) should be used to clear down the test data which was
used by the actual test. You should use this method to clear the test data and make
sure they are ready to use by the next Test method. This method would be called
after calling the test method by the ABAP Unit framework. Similar to SETUP, this
method would be called as many times as many test methods are there in a single
test class.
In this method, you should generally setup your test data which can be leveraged by
various different test within the same test class. Simple example, would be to
clear the product code objects or all attributes of the test class and make sure it
is ready for next execution.
Method CLASS_SETUP( ) & CLASS_TEARDOWN( )
Method CLASS_SETUP( ) is a static method. Set up the test data and save it into
some temporary variable. We can use these test data into the SETUP method. The
purpose of CLASS_SETUP is to set up the same data like a configuration which would
be used by all test methods but NONE of the test method would be modifying it.
Static method CLASS_TEARDOWN would to make sure you clear up all the data and
related attributes used in the test class before leaving the class.
Demo Program
Check out this demo program to display the use of test fixture.
REPORT ZNP_AUNIT_FIXTURE_DEMO.
*&---------------------------------------------------------------------*
*& Purpose - ABAP Unit fixture methods demo
*& Author - Naimesh Patel
*& URL - http://zevolving.com/?p=2228
*&---------------------------------------------------------------------*
*
CLASS lcl_data DEFINITION.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_data,
glacc TYPE char10,
dmbtr TYPE bseg-dmbtr,
END OF ty_data.
TYPES: tt_data TYPE STANDARD TABLE OF ty_data.
DATA: t_data TYPE tt_data.
METHODS: get_sum_for_glacc IMPORTING iv_glacc TYPE char10
RETURNING value(rv_amt) TYPE bseg-dmbtr.
START-OF-SELECTION.
*
CLASS lcl_data IMPLEMENTATION.
METHOD get_sum_for_glacc.
DATA: ls_data LIKE LINE OF t_data.
LOOP AT t_data INTO ls_data WHERE glacc = iv_glacc.
rv_amt = rv_amt + ls_data-dmbtr.
ENDLOOP.
ENDMETHOD. "get_sum_for_glacc
ENDCLASS. "lcl_data IMPLEMENTATION
*
CLASS lcl_test_collect DEFINITION FOR TESTING
"#AU Risk_Level Harmless
"#AU Duration Short
.
PRIVATE SECTION.
DATA: o_cut TYPE REF TO lcl_data.
METHODS:
setup,
teardown,
test_valid_gl FOR TESTING,
test_invalid_gl FOR TESTING.
ENDCLASS. "lcl_test_collect DEFINITION
*
CLASS lcl_test_collect IMPLEMENTATION.
METHOD setup.
DATA: ls_data LIKE LINE OF o_cut->t_data.
CREATE OBJECT o_cut.
ls_data-glacc = '101'. ls_data-dmbtr = '20'.
APPEND ls_data TO o_cut->t_data.
ls_data-glacc = '101'. ls_data-dmbtr = '30'.
APPEND ls_data TO o_cut->t_data.
ls_data-glacc = '102'. ls_data-dmbtr = '40'.
APPEND ls_data TO o_cut->t_data.
ls_data-glacc = '101'. ls_data-dmbtr = '50'.
APPEND ls_data TO o_cut->t_data.
ENDMETHOD. "setup
METHOD teardown.
CLEAR o_cut.
ENDMETHOD. "teardown
METHOD test_valid_gl.
DATA: lv_result_amt TYPE bseg-dmbtr.
lv_result_amt = o_cut->get_sum_for_glacc( '101' ).
cl_aunit_assert=>assert_equals(
exp = 100
act = lv_result_amt
msg = 'Total is incorrect'
).
ENDMETHOD. "test_valid_gl
METHOD test_invalid_gl.
DATA: lv_result_amt TYPE bseg-dmbtr.
lv_result_amt = o_cut->get_sum_for_glacc( '999' ).
cl_aunit_assert=>assert_equals(
exp = 0
act = lv_result_amt
msg = 'Total is incorrect'
).
ENDMETHOD. "test_invalid_gl
ENDCLASS. "lcl_test_collect IMPLEMENTATION
AS rule of TDD you start with empty production method and initial test.
After implementing the logic and re-factoring the test, you would notice your test
is getting successful.
RS_AU_SAMPL_FIXTURE_PATTERNS
Since ABAP release 731, you have the report RS_AU_SAMPL_FIXTURE_PATTERNS to show
different usage. The program is also well commented :)
By Naimesh Patel | April 18, 2013 | ABAP Objects, ABAP Unit Test | 13,886 | 5
ABAP Unit is an embedded framework to develop using the Test Driven Development
approach. ABAP unit lets you test the code at unit level, independent of the entire
solution.
1 Preface
2 Basic Example:
2.1
3 Test Class setup
3.1
4 Test method implementation
4.1
5 Initial Run
6 On to Next Article
Preface
I have mentioned many times in the various articles about ABAP Unit. With this new
series of articles, I would try to help you understand the ABAP Unit and encourage
you to leverage it.
ABAP unit lets you test the code at unit level like testing each piece separately.
Thus making sure it would function and produce desired results when those piece
would be put together in the puzzle.
Basic Example:
As a starting point, let’s start with a basic example so you can get introduced to
the framework. This basic example has a class LCL_SUM with a method SUM. This
method’s responsibility is to ADD up the numbers. It takes a number as importing
parameter and then adds it to itself to derive the result. This method SUM is
referred as Production Method in Unit Test concept. I will cover more on the
concepts in next article.
*
CLASS lcl_sum DEFINITION.
PUBLIC SECTION.
METHODS: sum IMPORTING iv_1 TYPE i
RETURNING value(rv_sum) TYPE i.
ENDCLASS. "lcl_sum DEFINITION
*
START-OF-SELECTION.
* Nothing here yet
*
*
CLASS lcl_sum IMPLEMENTATION.
METHOD sum.
rv_sum = iv_1 * iv_1.
ENDMETHOD. "sum
ENDCLASS. "lcl_sum IMPLEMENTATION
To declare a class which acts as test class, you would need to add the keyword FOR
TESTING when defining the class. This addition separates this class from the
production code. Similarly, you need to add the keyword FOR TESTING to the method
to make a test method.
*
CLASS lcl_test DEFINITION FOR TESTING
"#AU Risk_Level Harmless
"#AU Duration Short
.
PUBLIC SECTION.
METHODS: m_sum FOR TESTING.
ENDCLASS. "lcl_test DEFINITION
*
CLASS lcl_test IMPLEMENTATION.
METHOD m_sum.
ENDMETHOD. "m_sum
ENDCLASS. "lcl_test IMPLEMENTATION
As you might notice here, I have also added pseudo comments #AU Risk_Level and #AU
Duration. Prior to ABAP 7.02 Pseudo comments are used to let the framework know
more about the ABAP unit class. In the version 7.02 on wards, it has be replaced
with addition RISK LEVEL and DURATION.
Test method implementation
In this test method, what you need to do is – Test the production code. So, to be
able to test method SUM of LCL_SUM, you would need to instantiate a object
reference to LCL_SUM, call the method SUM sending the dummy value. Based on the
Dummy value, the method would send you the result – the actual result from the
method. Based on Dummy value, you know what would be expected value. E.g. If you
pass number 3 to SUM method, it would give you the result of 6 as it is adding 3 to
3.
Once you receive the actual result from the production code or method under test,
you need to compare the results. If the actual vs expected is not matching, you
need to let the ABAP Unit framework know that something is wrong with the actual vs
Expected. To be able to do this you can use the methods from the class
CL_AUNIT_ASSERT. For this demo purpose, we would use method ASSERT_EQUALS.
*
CLASS lcl_test IMPLEMENTATION.
METHOD m_sum.
DATA: o_cut TYPE REF TO lcl_sum.
DATA: lv_result TYPE i.
*
CREATE OBJECT o_cut.
lv_result = o_cut->sum( 3 ).
*
cl_aunit_assert=>assert_equals(
exp = 6
act = lv_result
msg = 'something wrong'
).
ENDMETHOD. "m_sum
ENDCLASS. "lcl_test IMPLEMENTATION
Initial Run
Now you have your test class and a test method ready. Its time to run it and verify
the result. You can run the ABAP Unit from the menu Program → Test → Unit Test.
ABAP Unit Run from Menu
When you see the ABAP Unit Results Display, you would know that there is something
wrong. On the right bottom side of the screen, You would see both of the values –
Actual 9 vs Expected 6.
ABAP Unit Results Screen
This tells me that, there is something wrong the production method implementation.
Yeah, If you look closely the method implementation of the SUM, I have a typo –
instead of using Summation, I had used Multiplication. So, I would correct it and
re-run the test. This time, since I have a correct code, you would see the ABAP
unit results like this:
ABAP Unit Success message
On to Next Article
In the next article, I would cover basics of ABAP Unit along with Test Driven
Development (TDD) as well. Stay tuned!
By Naimesh Patel | May 13, 2013 | ABAP Objects, ABAP Unit Test | 5,729 | 2
Since ABAP release 7.0, you can create ABAP Unit Test Global Class. Lets see what
to do and what not to when using the ABAP Unit Global Test Class.
Preface
ABAP Unit testing was introduced as part of the ABAP Release 6.40. The global test
classes were introduced in the next release i.e. ABAP Release 7.0. Lets talk about
the ABAP Unit Global test class. Before we jump in, check out the already posted
(and in pipeline) articles:
When you create a class in SE24 or in SE80, you can specify the category of the
class. Here you have an option to make any class as Global Unit Test class by
selecting Test Class (ABAP Unit).
ABAP Unit Global Class Definition
Once the class is created, you can specify the Runtime Limit and Risk Level.
You might have noticed that I have created class as Abstract Instantiation. Before
we talk about that, lets see different type of usage of Global Test class.
Helper Class
These class would contain the methods which would be used or leveraged in building
up part of test fixture. Although, these type of class would be tagged with FOR
TESTING, you may not create any test method as such. This class may also not
contain any full test fixture method, but it would have a smaller helper methods to
be part of fixture.
Parent Unit Test
This type of class may contain at least one test method. It may also contain a
fixture method. You can inherit your local test class from this global class. You
can create a Global Unit Test class with few test methods and reuse that while
defining the local test class. Since, you wont be able to instantiate the object as
well as you don’t want to have lot of programs using the same class, you should
create the class as Abstract class.
Demo
In his Demo, I have the the logic to build a “packet” from a bigger dataset.
METHOD build_itab_all.
ENDMETHOD.
methods MAKE_PACKET
returning
value(RT_PACKET) type TREXT_STRING .
*"* use this source file for any type declarations (class
*"* definitions, interfaces or data types) you need for method
*"* implementation or private method's signature
PRIVATE SECTION.
METHODS: setup,
test_packet_2 FOR TESTING.
ENDCLASS.
lt_result_itab = o_cut->make_packet( ).
cl_aunit_assert=>assert_equals(
exp = lt_exp_itab
act = lt_result_itab
msg = 'Unable to create proper packet'
).
ENDMETHOD. "test_packet_2
ENDCLASS. "lcl_test_packet IMPLEMENTATION
METHOD make_packet.
ENDMETHOD.
As soon as you add the logic and run again, you would see that your test passes !!!
Few Guidelines on using ABAP Global Test class
Refrain of using the Global test class as Parent Test class. This would get
executed in all the test classes where ever the local class is inheriting the
class. It may be unnecessary.
Make your helper class as Test class as well by adding the FOR TESTING as you
don’t want it to run in production
Use test class to build up smaller chunk of the text fixtures which can be
reused in your various test cases
All instance methods are by default for testing. So, make sure you remove it
for testing as you don’t want to create test methods in the Global test class