-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
1/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 3
Jrgen Staader studied
mechanical engineering at
the University of Stuttgart,
Germany. After working for
five years at an engineering
company, Jrgen joined
SAP in 2000. Since then,
he has been engaged in the
design, development, andmaintenance of various test
tools for ABAP, C/C++, and
Java, including ABAP Unit.
Jrgen can be reached at
How many ABAP developers can honestly say that testing is their
favorite aspect of software development? Hmmm, it sounds pretty
quiet out there. Implementing tests often feels like a tedious waste of
time. After all, testing just proves the correctness of the code, right?
And being good developers, dont we all code correctly anyway?
On the other hand, we are well-educated developers, and as such
we are fully aware of the utmost importance of thorough automated
testing.
Until now, ABAP developers had no viable way of resolving the
conflict between the importance of testing during development and the
available options for automating it. Starting with SAP Web Application
Server (SAP Web AS) Release 6.40, a new tool called ABAP Unit enters
the stage with the following benefits:
ABAP Unit allows you to concentrate on the test coding, rather
than how to run the tests or how to interpret and represent the
results.
Tests become an integrated development aid, rather than an extra
task purely for meeting quality standards.
Individual tests quickly accumulate to form comprehensive test
suites that can be run automatically.
Successful execution of test suites validates the quality of your
software.
Attention ABAP Developers!
Boost the Quality of Your Programs
by Writing Automated Unit Tests
with ABAP Unit
J rgen Staader
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
2/32
SAP Professional J ournal J anuary/February 2005
4 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
This article introduces you to the ABAP Unit
test tool and shows you how to use it effectively,
saving you valuable time and effort, while at the
same time producing higher-quality code. First,
well look at the principles and benefits of unit test-ing. Then, well look at ABAP Unit itself and how
it works, including how to create, run, and interpret
unit tests.
Principles and Benefitsof Unit Testing
In order to understand the full value of ABAP
Unit, lets start by considering the nature of a unit
test. According to the Institute of Electrical and
Electronics Engineers (IEEE), unit testing means
testing of individual hardware or software units or
groups of related units.1
The meaningful unit for a unit test must be a
nontrivial, accessible code fragment in which a
given input or action causes a verifiable effect. In
ABAP, a unit is typically a single method, a function
module, or a form. Ideally, you should test such
a unit in isolation from any other unit, so it does
not depend on the execution of any other portionof the code.
This definition offers the key to the benefits of
unit testing. Since a good unit test doesnt rely on
any dependent code, early testing is possible. Also,
because the scope in which you search for an error is
strictly limited, error detection is easier. And finally,
addressing a nontrivial portion of the code avoids
wasting time testing things that could not possibly
break, such as a single-line accessor method in
ABAP Objects.
Next, well take a look at how the unit testing
approach compares with the classic functional testing
approach.
Continuous Unit Testing vs.Downstream Functional Testing
Traditionally, the testing phase for ABAP projects
begins only after all the code is written. At first
glance, this sequence seems logical; after all, how
can we test something that does not yet exist?2
However, if you restrict testing to isolated units
i.e., if you split your coding into small, independent
portions you no longer need to wait until you
complete the project to test it, in order to be sure
that all code dependencies are covered. Instead,
you can begin unit testing during the development
phase itself.
One problem with having a dedicated testing
phase downstream from the implementation phaseis that you find bugs comparatively late in the proj-
ect. Until then, you and your fellow project team
members work with buggy code and spend valuable
time searching for and fixing inherent bugs instead
of writing new code. The system becomes increas-
ingly more complete and complex as the implemen-
tation phase progresses, thus the later a bug is
found, the harder it is to identify, and the more
expensive it becomes to correct. In contrast, unit
testing helps you detect bugs early in the implemen-
tation phase.
Another problem of downstream testing relates
to project schedules that are typically fixed well
in advance. If some unforeseen incident delays
progress, you might be tempted to meet a deadline
at the expense of shortening the testing phase, a
tradeoff that would clearly affect project quality. In
contrast, unit testing allows you to distribute tests
throughout the implementation phase, which fosters
confidence in your code at all times. This approach
also reduces the risk of unpleasant surprises during
final testing.
While automated functional testing is well-
covered by the extended Computer Aided Test Tool
1IEEE Standard Glossary of Software Engineering Terminology,Standard #610.12-1990.
2Later in the article I will revisit this question, and show that itactually can make a lot of sense to write tests for something thatdoes not yet exist.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
3/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 5
(eCATT),3 there has been no tool support for auto-
mated unit testing in ABAP until now. This article
shows you how the new ABAP Unit tool closes the
unit testing gap.
So what does all this mean in terms of who is
responsible for implementing the tests? Well look at
this next.
Unit Tests Are Developer Tests
While classic functional testing of a complete system
is typically performed by dedicated quality engineers
with specialized job profiles, unit tests are best created
by the developers of the units to be tested.
A closer look at the development process reveals
that most developers already perform some type of
testing during the implementation phase it is just
perceived as part of the development effort rather than
as an extra testing task. For example, suppose you
want to check whether a newly written part of the
code (e.g., a function) behaves as expected before you
write the next piece of code. You would typically
write a temporary test code fragment that provides
some (more or less meaningful) test data to satisfy
the functions signature, and then call the function.
(Congratulations, by the way you just wrote aunit test!)
Then, you set a breakpoint in the function entry
and check whether the code behaves as intended. This
initial effort is small compared to creating an auto-
mated, repeatable test. Nevertheless, if you need to
test this piece of code again (at least once after each
subsequent modification), you may soon wish you had
spent a little extra effort up front to make this testing
(and your life) a bit easier.
As this example shows, classic developer testsconsist of writing temporary test fragments and
debugging. Many developers also use tracing, or a
combination of these techniques, to test their code.
The drawbacks of these techniques are evident.
Debugging takes time and effort, and tracing
quickly produces unmanageable amounts of informa-tion you need to analyze. Because it is difficult to
anticipate which specific details are useful, you typi-
cally need to capture a vast amount of information in
each trace, which has the effect of obscuring the vital
information (i.e., causing scroll-blindness). Also,
just because a piece of code works now doesnt guar-
antee that it will after the next few development itera-
tions, so you need to constantly retest it a task that
can become monumental as the code increases in size
and complexity. Ideally, you do not want to be both-
ered with testing a piece of code after you have deter-
mined it is correct. You want automated, unattended,repeatable tests, but temporary test code, debugging,
and tracing dont produce results that can be used for
this purpose.
What is a developer to do? Turn to the ABAP
Unit test tool.
This article shows you how to use ABAP Unit
functionality to create repeatable test code that guar-
antees once-working functionality is never broken by
a later modification (also known as regression test-
ing), and in turn reduces the amount of hiddenextra testing effort you need to expend during devel-
opment. Although it requires some extra time and
effort up front to write unit tests, it more than pays for
itself down the road when you have fewer bugs, and
need less time to fix them.
Unit Tests Are Beneficial forMaintenance, Too
I have emphasized the advantages of being able to test
early and often during development. However, thevalue of unit testing isnt restricted to the development
phase of the software lifecycle unit tests are useful
during the maintenance phase as well.
If a bug only arises in production, write a unit
test to identify and reproduce the bug. Then fix the
3For more information, see the article Extend the Range and Reducethe Costs of Your SAP Testing Activities with eCATT in theJanuary/February 2003 issue ofSAP Professional Journal.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
4/32
SAP Professional J ournal J anuary/February 2005
6 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
bug and validate it using this unit test. Using unit
tests for regression testing ensures that this bug never
reappears. This article teaches you how to write such
a test.
Unit Tests Are Easier Than You Think
The charm of ABAP Unit is that you need to learn
very little in order to reap its benefits. You write the
tests in the language with which you are already
familiar (ABAP) and in the environment that you use
all the time (the ABAP Workbench).
This article teaches you everything you need
to know to get started putting ABAP Unit to workfor you.
The Basics What Is ABAP Unit?
Unit testing tools have existed for some time for most
modern programming languages. ABAP Unit is the
new tool that brings unit testing capabilities, and thus
all their advantages, into the ABAP environment.4 As
you will see, ABAP Unit additionally enhances the
unit testing concept with its close integration into the
ABAP language, and its support for mass testing as
well as individual testing.
From a developers perspective, ABAP Unit con-
sists of:
The ability to write a unit test in ABAP with des-
ignated test classes and test methods
Commands to run unit tests on programs fromwithin the ABAP Workbench
A result display for analyzing unit test errors
Integration into and extension of the ABAP
Code Inspector (transaction SCI) for running
mass tests5
You run the ABAP Unit tool for at least one
program, for which ABAP Unit calls all the tests
that were embedded into that program. You can
add ABAP Unit tests to any of the following pro-
gram types:
Four Steps to Creating a Unit Test
1. Consider what you want to test (that is,
the unit to be tested), such as a functionmodule or a specific method of a class.This tested code belongs to an ABAPprogram, and its unit test is part of thesame program.
2. Add the unit test to the program. Youwrite unit tests in ordinary ABAP usingthe editor for the program, such as theABAP Editor (transaction SE38) forreports or the Class Builder (transactionSE24) for global classes.
3. Run the unit test from the ABAP
Workbench via the menu commandprovided by the particular editor inuse (Figure 11 later in the articlesummarizes these commands).
4. Analyze the results in case of failure.Keep in mind that a successful testsimply raises a success message.
4Unit testing tools for many languages are typically based on an underly-ing architecture called xUnit, a language-independent test frameworkthat ties back to Kent Beck and originated in a test tool for SmallTalk(sometimes referred to as SUnit). This testing concept and its testframework architecture became very popular with the Java implementa-tion JUnit, which was written by Erich Gamma and Kent Beck. ABAPUnit follows in this tradition.
5See the article Evaluating the Quality of Your ABAP Programs andOther Repository Objects with the Code Inspector (SAP Professional
Journal, January/February 2003).
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
5/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 7
Executable programs
Module pools
Function groups
Class pools6
So, what does an actual ABAP Unit test look like
when it is embedded within a program?
Because you write ABAP Unit tests in ABAP
(see the sidebar on the previous page), a procedure
call looks exactly the same in both the regular produc-
tion code and in the test code. There is no real differ-
ence from a code perspective. You dont need to
learn a new language for testing and continuallyswitch between production and test languages.
You implement ABAP Unit test code in test meth-
ods inside test classes, which are then added to the
code of the tested program. In order to express the
test nature of these classes and methods, the ABAP
language syntax was extended by the new FORTESTING addition. A test class is simply a local classwith FOR TESTING added to its definition. A testmethod is an instance method, without parameters,
that is inside a test class that has FOR TESTING
added to its definition.
The following example shows some code for
defining a test class (test_class) that has a singletest method (test_method):
class test_class definition for
testing.private section.methods:
test_method for testing.endclass.
Contrary to the test definition, where the FORTESTING addition identifies the test nature of theclasses and methods, the actual test implementation
is no different from an ordinary production class
implementation. The only thing you need from thetesting context of ABAP Unit is a service class,
which provides a number of static methods that allow
you to positively verify your test assumptions.
I discuss the methods of this service class in
detail later in the article.
6A class pool is the ABAP program frame for a global class. It is auto-matically generated when you create a new global class using the ClassBuilder (transaction SE24). A class pool serves as the container forexactly one global class, therefore, inside a class pool means the sameas inside a global class.
Private vs. Public SectionDeclarations
Experienced ABAP Objects programmersmay wonder why this example declares the
test method in the private section. This
declaration prevents external use of the test
method; a declaration in the public section
would allow external use. While not required,
this type of declaration is typical because you
rarely want to call test methods explicitly.
Instead, you simply enter the appropriate
command for ABAP Unit to run the test.
The test driver has an implicit friend
relationship to all tests, meaning that it can
run any test regardless of its visibility (public,
protected, or private).
In rare cases, you might prefer a visibility other
than private:
If you choose protected, you typically intend
to derive a test class from another test class,
and also want to run the inherited test methods
in the derived test class.
If you choose public, you intend to use
delegation, meaning that you want to use test
code from one test class in another test class
(for example, if you want to call a test method
of one test class multiple times from a testmethod of another test class).
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
6/32
SAP Professional J ournal J anuary/February 2005
8 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
Figure 1 illustrates the ABAP Unit test hierarchy.
A test task (which ABAP Unit automatically creates
for you) defines the programs to be tested together in
a single test run. When running ABAP Unit from
within the ABAP Workbench, the test task consists of
exactly one program the one that is currently open
in the particular editor in use. Each program can havemany test classes, each of which can contain many
test methods.
Creating a ProgramExample to Unit Test
The aim of unit testing is to check and prove that the
units e.g., the methods, function modules, or forms
of a program work properly. The tested program iscommonly referred to as the program under test.
Before expanding the test example (the test_class
definition in the previous section), we first need some
imaginary production code we can test.
For simplicity, the examples in this article use the
well-known flight data model used in ABAP training
and SAP documentation for demonstration and training
purposes. All shipped SAP systems include its corre-
sponding database tables. Using the Class Builder
(transaction SE24), create a CL_AIR_CARRIERS
global class as a simple wrapper for the SCARR data-
base table. This class applies to air carriers and includes
methods to add or delete a carrier, obtain the name andWeb address for a specified carrier ID, and retrieve the
number of all available carriers (see Figure 2).
Following the Examples
When following these examples in the Customer
namespace, you may need to insert Y_, Z_ , or your
company name as a prefix to the class name.
The examples in this article only use theADD and
GET_COUNTmethods of the CL_AIR_CARRIERS
class. To follow along, simply create a global class
with these two methods only and specify the signature
for them. TheADD method has one input parameter:
Figure 1 ABAP Unit Test Hierarchy
The actual tests are implemented as test methods,which are grouped in the test classes
Program A Program B
Test Class D Test Class E
TestMethodTest
MethodTestMethod
TestMethodTest
MethodTestMethod
TestMethodTest
MethodTestMethod
Test Class B Test Class CTest Class A
Test Task
Program C
The programs being tested (i.e., undertest) are aggregated in a test task
Test classes belong organizationally andphysically to the program under test
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
7/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 9
importing AIRLINE type SCARR
The GET_COUNTmethod returns the following
result:
returning value(RESULT) type I.
This will probably surprise you, but you can ignorethe actual implementation of the production code for
now all you need is the class definition in order to
compile the unit tests. It doesnt even matter whether
the method bodies contain any code at this point.
Consequently, you really dont need the actual imple-
mentation of a class in order to test it! Of course, the
tests will fail without a corresponding implementation
of the production code, but once you have created all
the necessary tests, you can gradually implement your
production code and continually test it along the way.
With this approach, the further you proceed with the
production code, the fewer failures your tests will pro-
duce. Quite simply, you are finished when all yourtests succeed. This development strategy, which was
first introduced by the Extreme Programming (XP)
methodology, is known as the Test First principle
(see the sidebar below).
Figure 2 Example CL_AIR_CARRIERS Class Definition
The Role of Unit Testing in Lightweight Programming Methodologies
The modern lightweight programming methodology Extreme Programming (XP) has played a
significant role in the broad acceptance of unit testing unit testing supports and enables collectivecode ownership and continuous software refinement, which are key elements of this programming
practice.
Kent Beck, initiator of XP and author of the book Extreme Programming Explained: Embrace Change,points out that none of the ideas in XP are new. Most are as old as programming. He sees the
(continued on next page)
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
8/32
SAP Professional J ournal J anuary/February 2005
10 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
Now that we have something to test, lets create
the corresponding unit test that well use to test it.
Language-Integrated Unit Testing
So now that were ready to create a unit test for our
example class, where exactly do we create it?
Traditionally, production and test code are sepa-
rated into different compilation units such as physical
files or programs, depending on the language.
However, that separation is problematic because the
production and test code are logically very tightly
coupled. Presuming full test coverage, if you make
any interface or semantic changes in the production
code, you must also reflect the same changes in the
test code in order to run the tests successfully.
Unfortunately, the physical separation of the pro-
duction and test code complicates this fundamental
prerequisite. Keeping the production and test code
synchronized requires care and effort. Suppose some-
one changes the production code at some point in the
future. Might that person overlook the separate test
program associated with that code? (In an idealworld, appropriate test code exists for all production
code!) When the tests eventually fail, is the unfortu-
nate test author then responsible for tracking down the
developer who made the incomplete modification?
Ultimately, how can you ensure that both production
and test code are transported together?
This separation has an additional consequence that
is particularly relevant for ABAP. It means that the
tests have an external view into the production code,
which can make it difficult to fully test the production
code. Just think of what it takes to access and test a
local class inside a program from another program.
The left side ofFigure 3 illustrates this situation and
its potential problems.
The depiction of these difficulties imply what you
really need a common compilation unit for both
innovation in combining commonsense principles and practices. XP assures their thorough exertion and
mutual greatest possible support, and takes them to extreme levels hence the name.
Even if you arent using XP (and that is OK with Kent Beck, if you correctly decide not to use XP), its
great merit is still to show us quite plainly these very effective software practices and to remind us of theirvalue. Some of them are just as valuable to the conventional software development process.
In the context of unit testing, XP emphasizes test automation; the straightforward creation, management,and execution of tests; complete test coverage (except for trivial code like simple accessor methods); and
always-faultless test results. If a once-faultless test execution is no longer successful after a modification,then you know for sure that the modification broke the code.
XP also proposes that tests drive development, which means that you write the tests first and only then
write the production code the Test First principle. Of course, writing the tests before the productioncode means they will fail, and in fact not even compile, as there is no corresponding implementation, but it
allows you to clarify how the production code should look, and how you want to use it. Next, you providethe production code interfaces, so the tests compile, and then implement the production code itself. If the
existing tests succeed, think of additional tests that could possibly break the code. You know you havefinished the implementation when you cant identify any.
(continued from previous page)
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
9/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 11
production and test code. All the noted problems van-
ish with this approach, as you can see on the right side
of Figure 3. The internal view of the test code allows
the direct use of local classes inside programs such as
class pools, because the test classes are in the same
program. Synchronization problems are solved and
the tests that correspond to the code are clear since
they are embedded in the code to be tested. Transport
no longer requires synchronization because you have a
single, inseparable transport object. So why hasnt
this approach been taken before?
One problem is the potential for increased system
load. When tests are embedded in production code,
both entities must always be loaded together when
needed. If you take unit testing seriously, the amount
of test code could easily exceed the amount of produc-
tion code, so this approach would double the program
load, resulting in serious performance degradation
caused by code that isnt even relevant to production!
Another drawback is maintaining data integrity and
security. Because the tests themselves are written
in ABAP, they could potentially do things that are
Figure 3 External vs. Internal Test Code
Traditional Approach: Production Code andTest Code in Separate Compilation Units
Limitation: External view with limited accessto the implementation.
Problem: Version synchronization. Is there amatching test version for the production codeversion? Which is the matching test version?
Problem: Transport synchronization. Will thematching versions of the test and productioncode arrive together at their destinations?
ProductionCode
TestCode
ProductionCode
Version X
ProductionCodeVersion Y
ProductionCode
Version Z
TestCode
Version Z
TestCode
Version X
ProductionCode Transport
TestCode Transport
TestCode
ProductionCode
New Approach: Production Code and TestCode in a Common Compilation Unit
Internal view with unlimited access to theimplementation.
Version synchronization is not a problem.The test code is embedded within theproduction code.
No transport synchronization is necessary.The test code always comes along with theproduction code.
Test CodeVersion X
ProductionCode Version X
Test CodeVersion Z
ProductionCode Version Z
Production Code
Test Code
CommonCode Transport
Production Code
Test Code
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
10/32
SAP Professional J ournal J anuary/February 2005
12 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
unacceptable in a production system for example,
test operations might need to access the database or
even manipulate or delete database content. For theseperformance and security reasons, tests should never
be executed in a production environment.
So how do we get the benefits of this approach
without the risks?
The remedy is a new technique that SAP calls
language-integrated unit testing. In a production
environment, the tests are not part of the program load
(see Figure 4). The tests are simply not present. The
ABAP compiler distinguishes test code from regular
production code, and generates the appropriate pro-
gram load with or without the tests accordingly. In a
production environment, the program load excludes
local test classes marked as FOR TESTING.
The primary consequence of excluding test code
from production systems is that production code never
references any test code. Aside from the fact that
using or referencing test code in production code sim-
ply isnt meaningful, just imagine what would happen
if the production code were allowed to reference the
test code. The approach would work fine on a devel-opment system where the tests are part of the pro-
gram load. But once the program was moved to the
production environment, where the referenced test
code is no longer available, the program would
suddenly crash where it hurts the most during
production use.
But dont worry! All measures have been taken in
ABAP to make this consideration purely hypothetical.
Static integrity is guaranteed by a syntax check thatraises an error if you try to statically reference test
code in your production code. Dynamic integrity is
ensured by runtime checks. Any dynamic call from
production code to test code causes a runtime error. In
contrast, the test code always has full access to the
production code (see Figure 5).
Now you can place the test code in the same com-
pilation unit as the production code. That means
again speaking in ABAP terms to:
Put test classes for reports in the report.
Include dedicated test includes in function groups.
Put test classes in the local implementation of class
pools (choose Goto Class-local typesLocal
class implementations in the Class Builder).7
Our example global class CL_AIR_CARRIERSis the class under test in this article. The program
frame of a global class is a class pool, thus its test
classes reside in its local implementation part.
Figure 4 Program Load Without Test Code
Production Code
Test Code
Figure 5 No Access to Test Code
Production Code No access from productioncode to test code
Full access from test codeto production code
Test Code
7You can put isolated, independent test classes in their entirety (that is,both the class definition and implementation) in the local class imple-mentations section via this menu path. Alternatively, you can put thetest class definition in the local class definitions section via the menupath Goto Class-local typesLocal class definitions/types. If yourtest classes have dependencies (that is, if you are using test inheritanceor delegation), always put the test class definitions in the local class def-initions section.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
11/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 13
Now were ready to create a unit test for the classwe created back in Figure 2. Lets start by testing the
ADD method, beginning with the test definition. Openthe local implementation of the class under test (in this
case, CL_AIR_CARRIERS), and enter the followingtest definition:
class test_air_carriers definition
for testing.private section.
methods:add_carrier for testing.
data:cut type ref tocl_air_carriers.
endclass.
Compared to the first test example (the earlier
test_class definition), notice that this example
contains additional test data designed to avoid redun-dancy when you add more test methods. This code
fragment defines a reference (CUT) to the class undertest simply for accessing this instance. Defining this
reference once as a member of this class is more effi-
cient than defining it separately in every test method.
Next, supply the corresponding test implementa-
tion and fill it with some test code, as shown in
Figure 6.8
The test example is now complete and executable,
and calls the functionality to be examined. As you cansee, the implementation part doesnt contain any test-
specific syntax. It could just as well be production
Figure 6 The Test Implementation
8Note that SAP Professional Journal has not invested in air carriers forcloser contact with its international SAP community. This example usesa fictitious air carrier to avert suspicion of surreptitious advertising.
class test_air_carriers implementation.
method add_carrier.
data:
SAPproAir type scarr, " an air carrier we can addl_act type i. " the actual number of airlines
* create an instance of the class under test
create object cut.
* prepare some test data:
SAPproAir-carrid = 'S1'.SAPproAir-carrname = 'SAPpro Air'.
SAPproAir-url = 'http://www.SAPpro.com'.
* call the method under test:
cut->add( SAPproAir ).
endmethod.
endclass.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
12/32
SAP Professional J ournal J anuary/February 2005
14 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
code. Nevertheless, you wouldnt notice whether
theADD method executed correctly because youhave no way to verify the results of the method call.
What you need now is a way to express and verify
the expected test results. ABAP Unit provides asser-tion methods as part of its CL_AUNIT_ASSERTservice class for this purpose, which we will look at in
detail next.
Verifying Test Assertions
The CL_AUNIT_ASSERT service class providesseveral static assertion methods that you can use to
verify your test results. In case of failure, this class
launches an error that appears in the ABAP Unitresult display as an assertion error (see the sidebar on
page 25). Figure 7 lists the assertion methods along
with their required and optional9 parameters. In order
to choose the appropriate method, you need to under-
stand what each of them do. Lets take a closer look
at each in turn.
Understanding the Assertion MethodParameters
Lets start by reviewing the common parameters of allassertion methods. They all support the following
optional parameters:
MSG is a message of type CSEQUENCE thatidentifies the cause of the failure. Its default
value is the name of the called assertion method.
Although this parameter is not required, it is
good programming practice to always pass a
message to this parameter. This technique
expresses your intention for the test, providing
valuable test documentation and potential error
explanation.
LEVEL is the priority of the assertion error,
and has a value ofTOLERABLE, CRITICAL,
or FATAL, as defined in theIF_AUNIT_CONSTANTS interface and aliasedin the CL_AUNIT_ASSERT class. This parame-ter has theAUNIT_LEVEL dictionary type, and
its default value is CRITICAL. The ABAP Unitresult display reflects this prioritization, whichis particularly helpful during mass testing for
judging the significance of a unit test error and
prioritizing follow-up efforts. FATAL unit testerrors should obviously cause more alarm than
TOLERABLE errors. Regardless, your goalshould always be faultless unit test results,
and correcting unit test errors should receive
top priority!
QUIT affects the control flow of the test
execution with a value ofNO, METHOD,CLASS, or PROGRAM. This parameter has theAUNIT_FLOWCTRL dictionary type, and its
default value is METHOD. The possible valuesfor this parameter are defined in the
IF_AUNIT_CONSTANTS interface and aliasedin the CL_AUNIT_ASSERT class:
- NO means do not interrupt the test when anerror occurs and continue the test with the
statement that follows the failed assertion.
- METHOD means stop executing the testmethod when an error occurs. Remember that
the purpose of the test is to prove the correct-
ness of the tested production code. When that
is not the case, you want to stop the test
immediately and return from the method.
- CLASS means abort the test class executionand continue the test with the next test class.
- PROGRAM means the error is so serious thatcontinuing to test the program further makes
no sense. For example, you might use this
value if a necessary precondition is not met
(such as a missing resource), without which a
program cannot operate.
Some assertion methods also support one or more
of the following parameters:9 Note that optional applies to the ABAP signature extension, as well as
whether a default value is specified in the signature.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
13/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 15
ACT is the actual value of the assertion
verification, and is required by all of the assertion
methods except for FAIL. Pass the actual valueor reference that you want to check. The type is
usuallyANY, except forASSERT_DIFFERS(type SIMPLE) andASSERT_SUBRC (typeSYSUBRC).
EXP is the corresponding expected value for
assertions that compare the expected value with
the actual value. It is required by the assertion
methodsASSERT_EQUALS (typeANY) andASSERT_DIFFERS (type SIMPLE), and is
optional for the assertion method
ASSERT_SUBRC (type SYSUBRC).
Figure 7 ABAP Assertion Methods
Method Purpose Required Parameters Optional Parameters andParameters with Default Values
ASSERT_BOUND Ensure the validity of thereference for a referencevariable
ACT typeANY MSG type CSEQUENCELEVEL typeAUNIT_LEVEL*QUIT typeAUNIT_FLOWCTRL**
ASSERT_DIFFERS Ensure the differencebetween two simple data
objects (since SAP WebAS SP4 only)
ACT type SIMPLEEXP type SIMPLE
MSG type CSEQUENCELEVEL typeAUNIT_LEVEL*
TOL type FQUIT typeAUNIT_FLOWCTRL**
ASSERT_EQUALS Ensure the equality of
two data objects
ACT typeANY
EXP typeANY
MSG type CSEQUENCE
LEVEL typeAUNIT_LEVEL*TOL type F
QUIT typeAUNIT_FLOWCTRL**
ASSERT_INITIAL Ensure that an objecthas its initial value
ACT typeANY MSG type CSEQUENCELEVEL typeAUNIT_LEVEL*
QUIT typeAUNIT_FLOWCTRL**
ASSERT_NOT_BOUND Ensure the invalidity
of the reference for areference variable
ACT typeANY MSG type CSEQUENCE
LEVEL typeAUNIT_LEVEL*QUIT typeAUNIT_FLOWCTRL**
ASSERT_NOT_INITIAL
Ensure that an object
does not have its initialvalue
ACT typeANY MSG type CSEQUENCE
LEVEL typeAUNIT_LEVEL*QUIT typeAUNIT_FLOWCTRL**
ASSERT_SUBRC Expect a distinct value
for the return codeSY-SUBRC (since SAPWeb AS SP4 only)
ACT type SYSUBRC
EXP type SYSUBRC
MSG type CSEQUENCE
LEVEL typeAUNIT_LEVEL*QUIT typeAUNIT_FLOWCTRL**
FAIL Terminate the test withan error
None MSG type CSEQUENCELEVEL typeAUNIT_LEVEL*
QUIT typeAUNIT_FLOWCTRL**DETAIL type CSEQUENCE
* If you do not explicitly choose a value for the LEVEL parameter, the value will default to CRITICAL.** If you do not explicitly choose a value for the QUIT parameter, the value will default to METHOD.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
14/32
SAP Professional J ournal J anuary/February 2005
16 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
TOL is the tolerance (of type f). This optionalparameter applies only to comparisons of floating-
point numbers (via the assertion methods
ASSERT_DIFFERS andASSERT_EQUALS).
DETAIL is an additional detail message (of type
CSEQUENCE) that further describes the error.This optional parameter applies only to the FAILmethod, which doesnt provide any automatic
error analysis.
Now that you understand the assertion method
parameters, lets examine how and when to use each
of the assertion methods.
Using the General-Purpose FAIL AssertionMethod
FAIL is the simplest and most general assertionmethod. It supports the common parameters MSG,LEVEL, and QUIT, and the optional parameterDETAIL.
Calling FAIL unconditionally causes an assertionerror. This behavior is different from that of the asser-
tion methods with the prefixASSERT_, which verifythe specified assertion and indicate an error only if the
assertion is false. The error notification includes ananalysis of the error with a detailed message that
describes what is wrong with the assertion. The
FAIL method doesnt check anything; it merely sig-nals that an error occurred. Although the FAILmethod doesnt automatically provide any additional
information about the error, it supports parameters
for this purpose.
To provide additional information about the error,
call this method with the MSG parameter (to provide adescription of the error) and the DETAIL parameter
(to further explain the error situation). In the ABAPUnit result display, the DETAIL message appears inthe detail section for the error.
While you can use the FAIL method when youcant adequately express an assertion with the special-
ized assert methods, it is unlikely that you will
Exception Handling in Test Methods
Dont bother handling any unexpected class-based exceptions thrown by tested code. You dont need toenclose the test code in a try ... catch block in order to catch exceptions that are raised in your tested
production code, or construct an appropriate failure message. Simply leave the exception handling toABAP Unit, which is well-equipped for this task. Class-based exceptions appear in the ABAP Unit result
display as exception errors (see the sidebar on page 25 for more on the various ABAP Unit error types).The error message shows the exception type, and the detail section contains the exception text and thesource location where the exception was raised.
If the tested code raises an exception derived from the CX_STATIC_CHECKclass,* the syntax check
statically checks whether all exceptions that are raised or passed from a called procedure are eitherhandled by a CATCH clause or explicitly declared in the calling methods interface. In this case, you must
also declare the RAISING of this exception in the test method in order to propagate the exception to
* For more information about CX_STATIC_CHECKexceptions and class-based exception handling, see the article A ProgrammersGuide to the New Exception-Handling Concept in ABAP in the September/October 2002 issue of SAP Professional Journal.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
15/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 17
encounter such a scenario. FAIL is commonly usedto verify the flow control of test code. Insert the
FAIL method in control blocks that should not bepassed through, such as within an if else block:
IF logical_expression." test something
else.cl_aunit_assert=>fail( ).
endif.
Testing for exceptions also demonstrates a good
example of using the FAIL method (see the sidebarabove). In practice, this technique is perhaps the most
important use of the FAIL method.
Using the Specialized ASSERT_ AssertionMethods
The assertion methods that are specialized for a partic-
ular purpose all start with the prefixASSERT_. Eachmethod expresses a specific assertion to be verified
using built-in error analysis.
In case of an error (that is, if the assertion turns out
false), the error is reported. Unlike the FAIL method,
these methods automatically generate detailed informa-
tion about the error situation based on the specific
assertion without the need for additional parameters.
All of these assertion methods have the mandatory
ACT parameter that provides the actual value to be
examined. This parameter generally has the typeANY,
allowing you to pass data of any type;10 two methods
(ASSERT_DIFFERS andASSERT_SUBRC) require
ACT to have a more restricted type (SIMPLE and
SYSUBRC, respectively).
Using ASSERT_EQUALS for Comparing
Expected and Actual Results
Lets start with the most important, most useful asser-
tion method,ASSERT_EQUALS. Its usefulness stems
from the fact that in a test you usually want to compare
10ANY is the predefined generic ABAP type that can hold any arbitraryABAP data type.
ABAP Unit. As shown in the following example, use the CX_STATIC_CHECKabstract superclass todeclare that ABAP Unit handles all of its derived exceptions:
METHODS tip_exception_static_check FOR TESTING RAISING CX_STATIC_CHECK.
The only situation in which you would include a try catch block in your test code is when you wantto verify the actual raising of the exception, as shown in the following example, where the call of a
procedure correct_if_exception_raised is expected to raise an exception of the imaginary typeCX_EXPECTED_EXCEPTION_TYPE:
method tip_exception_wanted.
try.
correct_if_exception_raised( ).
cl_aunit_assert=>fail( msg = 'exception was not raised!' ).
catch CX_EXPECTED_EXCEPTION_TYPE.
* " if we get here, everything's fine.endtry.
endmethod.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
16/32
SAP Professional J ournal J anuary/February 2005
18 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
the actual state or result with the expected state or
result. Thus, in addition to theACT parameter for the
actual value, this method has a mandatory EXP param-
eter that provides the expected value. The following
example illustrates how to use this method:method test_fortune_teller.
data:
fortune_teller type ref to
cl_fortune_teller,
year type n length 4.
create object fortune_teller.
year = fortune_teller->the_year_
you_learned_ABAP_UNIT( ).
cl_aunit_assert=>assert_equals(
act = year
exp = '2005'
msg = 'fortune teller failed ' &
'on my ABAP knowledge' ).
endmethod.
In this example, you examine an imaginary
CL_FORTUNE_TELLER class to check the qualityof its forecasts in relation to ABAP Unit. Create a
FORTUNE_TELLER instance of this class and ask itin what year you learned how to use ABAP Unit.
Hopefully youll receive the right answer!
If the values are not equal, an assertion error is
launched. The detail section of the ABAP Unit result
display shows where and why the two values differed.While that information may not sound exciting for sim-
ple types (such as in the fortune teller example), it
becomes very interesting indeed for long character
sequences, structured types, or tables. Have you ever
tried to compare the contents of two large tables using
the ABAP Debugger to find the difference between
them? If so, you can greatly appreciate the fact that
ABAP Unit can tell you precisely that line 789 differs,
saving you from comparing the previous 788 lines
yourself.
Remember that complex types are all valid argu-
ments for theASSERT_EQUALSmethod becauseboth values have theANY generic data type. Beforecomparing the values, the method first ensures their
comparability. Comparability is weaker in this con-
text than for a direct comparison via the EQUALSoperator in ABAP. In other words, you can compare
values with ABAP Unit where a direct comparison
using the ABAP EQUALS operator would fail with aruntime error. For example, you could set up a stan-
dard table as the expected value and compare it with
actual sorted and/or hashed tables.
If values appear to be unequal, the detail section
of the ABAP Unit result display shows where the val-
ues differ. For long character sequences, the wildcard
symbol an asterisk (*) replaces matchingsequences. For instance, suppose you want to com-
pare the following strings:
This string is not very long but
just an example
and
This string is not so long butjust an example
The analysis that appears in the result display
would provide the following explanation:
Character String Different as of
Position 19Expected [*very*] Actual [*so*]
While seemingly insignificant in such a simple
case, this aspect of the error analysis is really helpful
for working with huge strings that you cant easily
compare at a glance.
The error analysis is even more beneficial for
comparing huge or nested tables with structured table
lines. The result display tells you exactly what is dif-
ferent if a single line is deleted, if lines are in a dif-
ferent order, or if an individual structure component
differs. Figure 8 shows a sample error analysis in a
partial screenshot of the ABAP Unit result display.
(I explain how to interpret this screen in more detail
later in the article.) This figure shows only the detail
analysis section, which appears in tree format. In
the left column, you expand and collapse the treebranches to display different granularities of the error
analysis. The right column contains the explanation.
Figure 8 shows the comparison of two internal
tables that could be in the internal data format of
our test example, which is a table of type SCARR.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
17/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 19
The first two lines that appear after the heading
Different Values show the size and the type of the
internal table:
Expected [S-Table[19x572] of \TYPE=SCARR]
The result display also shows lines in one table
that dont exist in the other:
Table Value Index [3] of Actual Table Not in
Expected Table
Expanding the tree branches further provides
more details, if available. It shows the differencesdown to the level of the relevant component if one
table line differs:
Different Table Values:
Component [MANDT] Different
Expected [000] Actual [ ]
You also see that the same item exists in both
tables but at different table indices:
Same Value at Different Table Indexes:
Expected [2], Actual [6]
Note that object references are compared for
identity only and not for content equality. In other
words, two object references are considered equal
only if they reference the very same object. Two
distinct objects with exactly the same contents eval-
uate to being different.
The ASSERT_EQUALS method has one more
optional parameter for tolerance, TOL. You only use
this parameter for comparisons of floating-point
numbers (of type f). Floating-point numbers cant
be represented exactly, as it is impossible to repre-
sent an infinite amount of real numbers in a finite
number of bits (or more precisely, in the finite num-
ber of 64 bits reserved by ABAP for floating-point
Figure 8 ABAP Unit Detail Analysis for a Table Comparison
Missingline inexpectedtable
Analysis down tocomponent of table line
Sameitem atdifferentindices
Size and type ofinternal table
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
18/32
SAP Professional J ournal J anuary/February 2005
20 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
numbers).11 This discrepancy becomes more appar-
ent because the internal representation is base 2,
instead of the more familiar base 10 representation.
In short, an exact comparison of floating-point val-
ues seldom behaves as expected. Therefore, you
specify a tolerance for expressing the range in which
you consider two numbers to be equal. This toler-
ance is the maximum absolute difference between
the two numbers for which the ASSERT_EQUALS
should conclude that the values are equal and the
check passes.
Using the Other ASSERT_ Methods Effectively
ABAP Unit provides several additionalASSERT_methods for other specific purposes:
ASSERT_DIFFERS
ASSERT_BOUND andASSERT_NOT_BOUND
ASSERT_INITIAL and
ASSERT_NOT_INITIAL ASSERT_SUBRC
TheASSERT_DIFFERSmethod is the oppositeof theASSERT_EQUALSmethod, with the limitationthat you can only use it with simple ABAP data types.
The simple generic data type includes the elementary
data types, as well as structured types with exclusively
character-type flat components.ASSERT_DIFFERShas essentially the same parameter list and semantics
asASSERT_EQUALS, except for the EXP parameter(which in this context really means not expected).
Continuing the fortune teller example from theASSERT_EQUALS discussion, the example in
Figure 9 uses theASSERT_DIFFERSmethod tocheck whether the fortune teller has a standard answer
to any question asking for a certain year. (For sim-
plicity, I excluded the declaration and creation sec-
tions.) Unless you are not completely new to
programming, this assertion should evaluate to true.
TheASSERT_DIFFERSmethod is one of thetwo exceptions where theACT parameter doesnt have
the generic ABAP typeANY instead,ACT and EXPhave the type SIMPLE. This limitation is due to theplausibility of such an assertion rather than a technical
constraint. It is certainly helpful to be able to verify
whether two timestamps or two unique identifiers are
different. Nevertheless, sensing that one component
of a complex data structure has changed is simply too
imprecise. A noted difference could have many
Figure 9 Using the ASSERT_DIFFERS Method
method test_fortune_teller_repetition.
data:
year_ABAP_UNIT type n length 4,year_programming type n length 4.
year_ABAP_UNIT = fortune_teller->the_year_you_learned_ABAP_UNIT( ).
year_programming = fortune_teller->the_year_you_learned_coding( ).
cl_aunit_assert=>assert_differs(act = year_ABAP_UNIT exp = year_programming
msg = 'fortune teller is repeating its standard answer' ).endmethod.
11Floating-point numbers are displayed internally with 16 decimal placesaccording to the IEEE-754 standard (double precision). For more informa-tion about floating-point arithmetic, refer to the bookThe Art of ComputerProgramming by Donald E. Knuth, or the paper What Every ComputerScientist Should Know About Floating-Point Arithmetic by DavidGoldberg (available at citeseer.ist.psu.edu/goldberg91what.html).
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
19/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 21
reasons. With simple data types, you can precisely
specify what you expect to be different.
TheASSERT_BOUNDmethod verifies that a ref-
erence variable contains a valid reference. It has thecommon parametersACT, MSG, QUIT, and LEVEL.This method behaves like the ABAP logical expres-
sion IS BOUND. It supports any type for the actualvalue (theACT parameter). However, the assertiononly passes if you pass data or an object typed with
REF TO. Otherwise, an error is launched.
TheASSERT_NOT_BOUNDmethod (which isthe opposite of theASSERT_BOUNDmethod) verifiesthat a reference variable does not contain a valid refer-
ence. It has the common parametersACT, MSG,
QUIT, and LEVEL. This method behaves like theABAP logical expression IS NOT BOUND. For theactual value (theACT parameter), you must pass dataor an object typed with REF TO. Otherwise, an erroris launched.
TheASSERT_INITIALmethod verifies that theactual value is initial i.e., that it contains its type-
specific initial value. It has the common parameters
ACT, MSG, QUIT, and LEVEL. This method behaveslike the ABAP logical expression IS INITIAL.
TheASSERT_NOT_INITIAL method (which isthe opposite of theASSERT_INITIALmethod) veri-fies that the actual value is not initial in other
words, that it contains a different value than its type-
specific initial value. It has the common parameters
ACT, MSG, QUIT, and LEVEL. This method behaveslike the ABAP logical expression IS NOT INITIAL.
Starting with SAP Web AS SP4, the new
ASSERT_SUBRCmethod allows you to verify thestate of the SY-SUBRC system field.12 After callinga statement that sets SY-SUBRC, it is sensible pro-
gramming practice to check its content before con-
tinuing the process. However, you cant easily
perform this check with the ASSERT_EQUALS
method. You would need to copy SY-SUBRC first,
because simply calling ASSERT_EQUALS would
reset SY-SUBRC to zero. This extra call is unneces-
sary with ASSERT_SUBRC, because with thismethod you pass the ACT parameter by value.13
Both the ACT and EXP parameters have the specific
dictionary type SYSUBRC. (This method is the other
exception for which the ACT and EXP parameters
dont have the generic type ANY.)
In general, an ABAP return value of zero means
that the statement was executed without problems.
In most cases, you dont need to explicitly specify
the expected value (the EXP parameter), since its
default value of zero is usually appropriate. You
could simply use the following statement:
cl_aunit_assert=>assert_subrc( act =
sy-subrc ).
You might choose to pass an explicit expected
value via the EXP parameter if you want to expli-
citly test a failure situation in which you expect
SY-SUBRC to have a value other than zero.
Checking the value ofSY-SUBRC is not the
only benefit of this method. Often, non-class-based
exceptions are used with ABAP messages (using theMESSAGE RAISING statement). Based on current
practices, you typically raise a message if a non-
class-based exception is not handled by the caller. If
ASSERT_SUBRC fails because of a return value that
is different from what was expected, the ABAP Unit
result display shows a possible corresponding mes-
sage in the detail view for the error.
Choosing an Assertion Method for the ExampleUnit Test
Armed with an understanding of the assertion
12 SY-SUBRC is an important system field that contains the return codeset by many ABAP statements. It is set to zero if the statement was suc-cessfully executed. Any other value signals a problem. Different valuesofSY-SUBRC are associated with different errors. See the ABAPonline documentation for further details.
13In the other assertion methods, all actual and expected values arepassed by reference (rather than by value) due to the generic natureof these values. Since anticipating the type of object to be passed isimpossible, general copying could introduce performance problemswhen passing huge tables or structures as parameters to the assertionmethods.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
20/32
SAP Professional J ournal J anuary/February 2005
22 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
methods, you can now complete the test example by
adding statements to verify the test assertion. The
first step is to choose the appropriate method from the
CL_AUNIT_ASSERT service class for this exam-ple,ASSERT_EQUALS.
After calling theADD method in theADD_CARRIER test method in the example test
implementation (Figure 6), you want to obtain the
actual value and compare it to the expected value. Inthis example, you want to check how many airlines
exist after adding one, which should be one. Insert the
following code at the end of the test method:
* after adding one airline
l_act = cut->get_count( ).cl_aunit_assert=>assert_equals(
act = l_actexp = 1
msg = 'after adding one ' &'airline'
).
If you are a distrustful person and you
absolutely should be when writing unit tests! you
also want to ensure that the newly created object didnt
contain any airlines before you added one. In other
words, you should check that the GET_COUNTmethod
really returned 0 before adding the airline.
Figure 10 shows the now-complete test example.
It creates an instance of the class under test and asserts
its initial state by checking that the air carrier counter is
really set to 0 (that is, it doesnt yet contain any carri-
ers). You provide an air carrier with valid data and add
it to the list, which is the method tested in the example.
Finally, the counter is checked again to verify that it
now contains exactly one air carrier.
The test for theADD method presumes that theGET_COUNTmethod works correctly, as the assertion
will fail if that method yields an incorrect value.
GET_COUNT is most likely a trivial getter method that
could not possibly break. Otherwise, you would also
need to explicitly check its correct operation in a dedi-
cated test method, so that you can rely on its results to
confirm other test expectations.
Running the Unit Test
Real developer tests (as opposed to tests that are typi-
cally run by dedicated quality assurance testers) should
be both written and executed within the development
environment. A shift in the working environment also
means a mental shift, which inherently creates more
effort for the developer and results in a loss of effi-
ciency. Experience also shows that developers are
Figure 10 The Complete Test Implementation
method add_carrier.
data:SAPproAir type scarr, " an air carrier we can add
l_act type i. " the actual number of airlines
* create an instance of the class under test
create object cut.* assert initial state
l_act = cut->get_count( ).cl_aunit_assert=>assert_equals(act = l_actexp = 0msg = 'before adding one airline'
).
* prepare the test data:
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
21/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 23
more willing to write tests if they stay in their familiar
development environment.
ABAP Unit embraces this principle. You run unit
tests for the program that is currently open in the
ABAP Workbench with the Unit Test menu command,
which is available from several different development
perspectives. In the Object Navigator (transaction
SE80), you run unit tests with the Unit Test command
on the context menu for the program (or part of it).
Figure 11 describes where to find the Unit Test
command in different ABAP Workbench screens.
SAPproAir-carrid = 'S1'.SAPproAir-carrname = 'SAPpro Air'.SAPproAir-currcode = 'USD'.SAPproAir-url = 'http://www.SAPpro.com'.
* call the method under test:
cut->add( SAPproAir ).
* after adding one airline
l_act = cut->get_count( ).cl_aunit_assert=>assert_equals(act = l_actexp = 1msg = 'after adding one airline'
).
endmethod.
Figure 11 How to Run ABAP Unit Tests
Tool (Transaction) View Menu Path
ABAP Editor (SE38) Initial Screen Program Execute Unit Test
Display Program Test Unit Test
Function Builder (SE37) Initial Screen Function Module Test Unit Test
Display Function Module Test Unit Test
Class Builder (SE24) Initial Screen Object type Unit Test
Class Definition Class Unit Test
Method Def. Method Unit Test
Public/Prot./Priv. Section Public/Prot./Priv. section Unit TestClass-local types Local types Unit Test
Loc. class implem. Unit TestMacros Unit Test
Object Navigator (SE80) Context menu on variousprogram types and parts of it
Unit TestExecute Unit Test
TestUnit Test
Figure 10 (continued)
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
22/32
SAP Professional J ournal J anuary/February 2005
24 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
If the tests run successfully, a success message
appears in the status bar, as shown in Figure 12.
If the program under test doesnt contain any tests,
the following message appears instead:
The active version of the class
contains no unit tests
If you see this message, check whether you saved
and activated the program under test. You can only
execute ABAP Unit tests after activating a program, as
you would for any ABAP program that you want to
compile and mark as executable in the system.
Interpreting Unit Test Results inthe ABAP Unit Result Display
The ABAP Unit result display appears automatically
if an ABAP Unit test run from within the ABAP
Workbench detects an error. This result display con-
sists of three parts, as shown in Figure 13. ABAP
Workbench test runs are considered to be personal
test runs for development purposes and are not saved
for future reference. You must use the ABAP Code
Inspector (transaction SCI) in order to run and save
the results of ABAP Unit tests (more on this in the
next section).
On the left side, you see an overview of the test
results in a tree format that reflects the test hierarchy
defined back in Figure 1. The test run in Figure 13
checked our example program CL_AIR_CARRIERS
with all its contained test classes and their contained
test methods. This test hierarchy for a test run is cre-
ated automatically when you run ABAP Unit for a
specific program. You expand or collapse the tree
branches in order to view summary results only, or
the results down to the granularity of each individualtest method.
Lets take a closer look at how to interpret the test
hierarchy. At the top of this tree display pane, you see
the test task, which is the test run by ABAP Unit.
ABAP Unit automatically creates the test task for you.
Its name contains the user name, the execution date
and time, and the system ID. When you run a test
from the ABAP Workbench, the test task comprises
exactly one program under test that is, the one
that is currently open in the development tool
(CL_AIR_CARRIERS in the example). Nested belowthat program, you see its active test classes and test
methods. The icon next to each item allows you to
quickly assess the aggregated state of the test for each:
A green circle means that the test was error-free.
A yellow triangle means that the test only pro-
duced TOLERABLE errors.
A red square means that the test produced at least
one CRITICAL or FATAL error.
On the right side of this tree display pane, you see
the total number of errors sorted by level or type. Use
the toggle button at the top of the tree display
to switch between the display variants. The error level
or priority shows the value that the test author speci-
fied for the LEVEL parameter (FATAL, CRITICAL,
Figure 12 Successful Test Message in Status Bar
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
23/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 25
or TOLERABLE), as described earlier in the section onthe ABAP Unit assertion methods. Remember that the
default value is CRITICAL for the LEVEL parameter
if it is not stated explicitly. The error type is one of
the four types described in the sidebar below (asser-
tion error, exception error, runtime error, or warning).
Figure 13 ABAP Unit Result View
Understanding the ABAP Unit Error Types
ABAP Unit supports four types of errors:
Assertion error: An assertion error is the most important error type because it is what you are
explicitly testing. In other words, an assertion error occurs if your test assertion is not true. In a way,these errors are anticipated errors since you typically test what might go wrong. In the example testmethod (Figure 10), the secondASSERT_EQUALS verification checks if theADD method doesnt exe-
cute properly and fails to add the airline. Of course, checking the counter is a rather weak testfor the successful addition of air carrier data. A more complete assertion would also verify correct
storage of the other information, such as the name and the currency.
Exception error: Exception errors are more commonly unanticipated errors. Perhaps creating theinstance does some complex things that could fail and raise an exception, such as retrieving data
(continued on next page)
Test Result Overview Message Details
Error Messages
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
24/32
SAP Professional J ournal J anuary/February 2005
26 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
On the upper right, you see the error message
pane. It lists all errors associated with your selection
in the tree display on the left. For example, if you
select the test task at the top of the tree, you see all
messages produced by the test run. If you select an
individual test method, you only see the messages
raised in that method. For assertion errors, the
Message Text column contains what you passed in the
assertion method for the MSG parameter. Exceptionerrors and runtime errors display the exception type.
Warnings display the warning message. Double-click
on any message to see its detail analysis.
On the lower right, you see the detail analysis
pane. Error analysis information appears under the
Info node, and the error location appears under the
Stack node. The error analysis provides an explana-
tion of the error message, indicating why ABAP Unit
concluded that the error occurred. For assertion
errors, this analysis describes why the assertion failed.
For example, if you compare two strings with the
ASSERT_EQUALSmethod, the error analysis indi-cates at what position and by what contents they dif-
fer. For exception errors, this analysis shows the
message of the raised exception. In the case of warn-
ings, you can possibly find some more detail informa-
tion here. In the case of assertion errors, the analysis
can obviously get quite extensive when comparing
from external resources or computing an initial state. You might not even be aware of this situation
if the exception is derived from the base exception CX_NO_CHECK. Regardless, you never needto catch any exceptions yourself. ABAP Unit simply handles the exception and presents it as anexception error.*
Runtime error: Runtime errors are the really bad errors. These errors are completely unexpected(so of course we dont expect to find one in our test example!). When you run a unit test in the
development environment, ABAP Unit doesnt catch runtime errors. Instead, you see the shortdump view of the runtime error just as if you executed the program normally. The runtime error
analysis provides detailed information to help you identify and resolve the problem. In a masstesting scenario, however, you dont want the test run to crash if one test produces a runtime error.Therefore, when you run an ABAP Unit mass test from the ABAP Code Inspector tool, in that context
ABAP Unit is able to catch and process runtime errors.
Warning: Warnings are messages that dont really indicate a problem in your tested code. Instead,they warn you about improper use of ABAP Unit. The following examples give you a sense of whatwarnings tell you:
- The message Test Program '' Could Not Be Generated could signify a syntax error inyour program.
- The message Constructor of Test Class '' Must Not Have Parameters indicates thatABAP Unit cant run the test class, because the ABAP Unit driver can only obtain an instance of atest class if its constructor doesnt have any parameters. Although syntactically correct, the test
class is not executable. To fix this warning, remove the parameters from the test class constructor.
(continued from previous page)
* Refer to the sidebar Exception Handling in Test Methods on page 16 for more information about class-based exceptions and how
to handle them.
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
25/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 27
objects with complex data types. You saw a good
example of this complexity back in Figure 8. The last
line below the Info node usually shows the location,
program, class, and method (if available) where the
error occurred. Below the Stack node, you find thetest-relevant stack information, the program and line
that guide you to the error location. Double-click on
any line in the error stack to navigate directly to the
relevant line of code in the appropriate editor.
You now have all the knowledge you need to write
and run unit tests. But there are a few more ABAP
Unit capabilities you can take advantage of to improve
your test design. Well take a look at these next.
Test Isolation
When introducing the unit test concept, I indicated
that you first identify a distinct unit of the program
that can be tested in isolation. Respecting this isola-
tion is important for several reasons:
If a completely isolated test fails, you can easily
locate the problem without analyzing any unfamil-
iar code dependencies.
Tests shouldnt interact with other tests, because
an individual test might either fail more frequentlydue to its dependencies, or simultaneously drag
many other tests to failure. This process not only
distracts you from the real source of the problem,
but being showered with unnecessary errors is
seriously discouraging!
In addition, isolation means not relying on any
particular test execution order. Even though a specific
test order may be respected in single test runs, the sit-
uation might be different in mass testing for perfor-
mance issues with parallelization. Thus ABAP Unit
has no guaranteed execution order for test methods!
Finally, isolation also means taking great care and
attention when accessing common resources, particu-
larly with database accesses. You must take into
account the possibility of other tests accessing the
same resource. Apply the same measures to make
concurrent access safe in test code as you would in
production code. In general, take as much care with
test code as you would with production code, even
though it is only for test purposes.
What does isolation mean in the context of a
test class? It means that the test fixture the
set of well-known test objects, meaning the data and
resources needed for a test is ideally exclusive to
each test in order to prevent tests from interfering with
each other. Otherwise, one test could modify the test
fixture in a way for which the next test is not pre-
pared. When introducing new test methods later, you
could inadvertently change the behavior of existing
test methods without being aware. Basically, you
need a clear and repeatable initial state of the fixture
used for each test.
Test Fixtures in ABAP Unit
ABAP Unit enforces certain principles with respect to
this isolation. Each test method automatically gets its
own newly created test instance. Therefore, changing
the instance in one test doesnt affect any other test.
Still, two methods of the same test class could
share class attributes. This possibility is restricted to
test methods within the same test class by running all
test methods of a test class in an isolated test session.
Never modify shared class resources in test methods,
because this technique is difficult and error prone.
An intentional modification of a shared class resource
would typically depend on a certain execution order
of the test methods, which isnt supported.
The test fixture consists of two components:
The class fixture refers to static data that exists
once for a test class.
The instance fixture exists once for each instance
of a test class.
How do you initialize the class and instance
fixtures? Performing this task clearly depends on a
dedicated execution point in the test sequence. The
class fixture initialization that provides commonly
used class data and resources must be reached before
running the first test method. Sometimes you also
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
26/32
SAP Professional J ournal J anuary/February 2005
28 www.SAPpro.com 2005 SAP Professional J ournal. Reproduction prohibited. All rights reserved.
need to clean up provided resources when no longer
needed. Therefore, you also need a second execution
point in the test sequence for triggering the cleanup,
which can only happen after executing all the tests of
one test class.
Lets examine the situation for the instance fix-
ture. Think of a typical test. You usually need test
data for modification or deletion. The test example in
this article provides a good illustration. All tests need
an instance of the tested CL_AIR_CARRIERS class.Defining this class as a class field isnt meaningful.
While many tests could modify its state, you need a
defined initial state of this instance in order to create
repeatable tests.
Alternatively, you could create an instance of the
CL_AIR_CARRIERS class at the beginning of eachtest method. While this approach might be manage-
able in the simple test example (the test_classdefinition from earlier in the article), because a single
statement constructs this instance, it is inconvenient
and means unnecessary redundancy. (Defining the
object reference CUT as an object member, rather thanas a local variable in each method, already eliminated
one line per method.)
You can easily imagine that common datasetup can be much more extensive and, based on
experience, require much more code than the actual
test itself. Thus, having a designated shared execution
point in the test execution sequence before and after
the execution of each test method would be very help-
ful. Not surprisingly, ABAP Unit supports such exe-
cution points, which are respectively referred to as
SETUP and TEARDOWN execution points.
Before examining where and how ABAP Unit
offers these execution points, and how to use them,lets outline the test execution sequence. Translating
the isolation measures and the identified consequen-
ces into an execution sequence produces the test exe-
cution structure shown in Figure 14. Note that the
SETUP and TEARDOWN execution points are optional.If you dont need them and dont implement them,
ABAP Unit simply ignores them. Optional steps
have a white background; required steps have a gray
background.14
This execution sequence applies only if your test
class provides specific methods with a specific name
and signature. The instance fixture methods are
SETUP and TEARDOWN, and the class fixture methodsare CLASS_SETUP and CLASS_TEARDOWN. Boththe instance and class fixture methods must be pri-
vate with no parameters. A syntax check warns you
if you try to declare fixture methods in a protected or
public section. (See the sidebar on the next page for
more on inheritance and fixture methods.)
Adding a Test Fixture to the Test Example
Suppose you want to further refine the test example to
check what happens if the same airline is added twice.
14The Nassi-Shneiderman diagram shown in Figure 14 is a graphical
method of representing algorithms that is easy to read even if youarent familiar with this diagram type. It signals the control flowof the algorithm from top to bottom. Unlike a program flow diagram,it has no connectors. The example in Figure 14 uses only twodiagram symbols the process symbol represented by a rectangle,and the iteration symbol indicating a loop, represented by the left-hand portion of the rectangle that spans all processes encompassedwithin the loop. It clearly shows the scope of the iteration. Formore information, refer to the paper Flowchart Techniques forStructure Programming by I. Nassi and B. Shneiderman (availableat www.geocities.com/SiliconValley/Way/4748/nsd.html).
Figure 14 Execution Algorithm
Class Construction of Test Class
Set Up Class Fixture
For Each Test Method
Create Test Instance
Set Up Instance Fixture
Run Test Method
Tear Down Instance Fixture
Tear Down Class Fixture
Start Internal Session for Test Class
-
7/29/2019 Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit.pdf
27/32
Attention ABAP Developers! Boost the Quality of Your Programs by Writing Automated Unit Tests with ABAP Unit
For site licenses and volume subscriptions, call 1-781-751-8799. 29
If we had completed our program example, the class
CL_AIR_CARRIERS, by adding its implementation,we sooner or later would have had to consider what
should happen in this situation. Most likely a list of air
carriers should not contain duplicate entries. Thus if a
particular air carrier is added a second time, the object
should still contain only one instance of that carrier.
Consequently, the unit tests for this purpose should be
Fixture Method Behavior in Derived Test Classes
Earlier in the article I discussed how you can declare test methods with different visibilities (PUBLIC,
PROTECTED, or PRIVATE) in order to express different uses for inheritance or delegation. However, youmust always define fixture methods (SETUP, TEARDOWN, CLASS_SETUP, and CLASS_TEARDOWN) in the
PRIVATE section of a test class. Only PRIVATE visibility ensures that these methods are directly relatedto their implementing class.
PRIVATE visibility prevents the instance fixture methods (SETUP and TEARDOWN) from being inherited by
derived test classes. If you define the SETUP method in a superclass, but not in its derived class, youwant the superclass setup to be executed exactly once (to set up the superclass), and not a second timefor the derived class. If the SETUP method had PUBLIC or PROTECTED visibility, the derived class would
inherit the method and run it a second time (unless the derived class redefines SETU