Testing in OO Environment

advertisement
Chapter 15
Object-Oriented Testing
Testing in OO Environment
• The reasons for testing is not any different for
any of the design and implementation
methodologies, including OO methodology.
– Find faults and fixing them before releasing
– Show that the software works (at least in chosen
areas)
• In OO we are especially interested in testing
because we want to “reuse” the tested objects.
• Does our approach have to change because of
OO?
– Not really - - - but we do have to focus on a few
characteristics
Issues in Testing Object-Oriented Software
• How is object-oriented (o-o) software different/special?
– Need to clarify unit
– Composition vs. decomposition
– No reason for integration testing based on functional
decomposition tree
– Can still use the (better) idea of Call Graph based integration
• Properties of an o-o programming language
– Inheritance
– Encapsulation
– Polymorphism
• Message communication
– Message quiescence
– Event quiescence
Basic Levels of Testing in OO
Same as before;
testing the whole
system
System Test
Unit A
Integration test
Unit X
Integration test
Unit
Testing
Same as before;
testing “related”
units as a group
What is a “unit”
In OO?
Units in Object-Oriented Software
•
Guidelines for units
– A unit is the smallest software component that can be
compiled and executed. (traditional view, usually in
procedural code)
– A unit is a software component that would never be assigned
to more than one designer to develop. (Project management
view, appropriate for both procedural and o-o software)
– Unit developer does detailed design, coding, and unit level
testing
• Candidate o-o units
– A single method
– A class (generally accepted view)
Single Methods as Units
• Appropriate for large classes
• Consistent with the one designer/one unit practice
• Single method testing
– reduces to unit testing for procedural units
– o-o units are typically less complex (cyclomatic) than
procedural units
• This choice mandates “intra-class” integration
testing.
Class and Object instantiation
•
There are at least two concerns with viewing class as
a “unit”:
1.
We should view Class as a fundamental unit and test it as an
independent entity by itself.
•
scaffolding
2.
integration
What and how much “scaffolding” code do we need to write to
invoke and test this Class.
–
–
e.g. Class1 x1; - - - You may need to write the public static void “main” method to test the
class (possible scaffolding code)
If there is a large method inside the Class and we know (via
white-box testing approach) that the method invokes other
methods in other Classes, should we follow (test) the thread of
methods across different Classes?
–
the module-module (mm-path) approach may be employed for
testing the “thread” of methods, that may go beyond one Class
3 important concepts in OO
1.
Encapsulation:
–
–
–
2.
In OO, the notion of self contained and only know/operate
within its own domain is very important
Good encapsulation gives rise to good reusable classes
that can be composed with other classes to deliver more
service.
We are also after highly cohesive and loosely coupled units
with encapsulation.
Inheritance:
–
A way to gain on the concept of reuse through a class
taking (inheriting) portions from a super class.
Overload/Polymorphism”
3.
–
Another way to gain on the reuse concept through using
parts of class or method for different purposes based on
the passed parameter or based on run time usage (late
binding).
How do these concepts affect us in testing?
Encapsulation
• Both data and methods may be encapsulated and
protected. Depending on the programming language
used there may be slight differences in implementing
the encapsulation mechanism:
– Public (visible) - - - pretty much same in all languages
– Private (hidden) - - - only methods in the class can access
– Protected (secret)- - - subclass methods can access
• Test the access of encapsulated data
• Test the access of encapsulated methods
Read the discussion on the positions of “dial’ and “lever” of the windshield wiper example
on page 287. The exchange of “positions” of these two may be different depends on the
design and how the data is encapsulated.
Inheritance Example (JAVA)
• One may want to test the methods in the inherited
class which were previously tested in the superclass.
• An example is a method, m1, that only returns positive
integers and is used in another method, m2, as a divisor.
An inherited subclass modifies (over rides) m1 to allow
all integers, including zero. (We will need to ensure that
the inherited and previously tested m2 is retested).
public class Example {
int y;
public int m1 {
y = (test * test) +1;
return y;
}
public void m2 {
z=w/y;
}
import Example ;
public class Example2 extends Example {
public int m1 {
y = test * test ;
return y;
}
}
Similar Inheritance Problem Example
(C++)
Class Test1 {
int some_variable;
.
Original CLASS
.
int method1 ( ) { return 1; }
int method2 ( ) { return 1 / method1( ); }
}
Class Test_child : Public Test1 {
int mehtod1 ( ) { return 0; }
}
Inherited CLASS
over-riding method1
Inheritance
• Do we need to test multiple inheritance,
where there may be conflicts in inheritance?
– Two subclasses, Sub1 and Sub2, are inherited from a superclass, S1, and they both modify the method, method1, but
differently. If we further inherit from both Sub1 and Sub2,
what should we expect method1 to be like?
Mother
Varx : int
method1 ( )
method2 ( )
Sibling 1
Note: JAVA does not allow
multiple inheritance
Sibling 2
(method1)
(method1)
overridden
Overridden differently
Grand_Sibling 1
Inheritance
•
Inheritance provides us with the ability to reuse (and save both
implementation and testing expenses) what is there and make
incremental changes by creating a subclass by either adding to or
modifying the :
–
–
•
Instance variable
Methods
Using “Flattened Class” concept:
1.
2.
3.
One may want to test subclass access of the “encapsulated” data or
methods in the super-class.
One may want to test all the methods in the inherited class which were
previously tested in the super-class.
•
An example is a method, m1, that only returns positive integers and is
used in another method, m2, as a divisor. An inherited subclass modifies
m1 to allow all integers, including zero. (We will need to ensure that the
inherited and previously tested m2 is retested).
Do we need to test multiple inheritance, where there may be conflicts in
inheritance?
•
Two subclasses, Sub1 and Sub2, are inherited from a super-class, S1,
and they both modify the method, m1, but differently. If we further inherit
from both Sub1 and Sub2, what should we expect m1 to be like?
Testing flattened Classes of all inherited subclasses will cause duplication of
testing the same (non-overridden) methods that appear in all the inherited subclasses
Implications of Inheritance
Account
accountNumber
Balance
getBalance()
setBalance()
checkingAccount
savingsAccount
checkProcessingCharge
checkNumber
interestRate
postCharge()
postInterest()
Implications of Inheritance—Flattened Classes
checkingAccount
savingsAccount
accountNumber
Balance
checkProcessingCharge
checkNumber
accountNumber
Balance
interestRate
getBalance()
setBalance()
postCharge()
getBalance()
setBalance()
postInterest()
Example—O-O Windshield Wiper
Class lever(leverPosition;
private senseLeverUp(),
private senseLeverDown() )
Class dial(dialPosition;
private senseDialUp(),
private senseDialDown() )
Class wiper(wiperSpeed;
setWiperSpeed(newSpeed) )
Which unit controls the interaction between
the Lever and the Dial?
Saturn Windshield Wiper Objects
Wiper
Speed
Lever Position
Dial Position
Compute Speed
Lever
Dial
position
position
Sense Up
Sense Down
Sense Left
Sense Right
Windshield Wiper Class Behavior
Lever
Dial
Wiper
Off
1
0 wipes/minute
leverDown
leverUp
2
Int
leverDown
leverUp
dialDown
dialUp
3
Low
6 wipes/minute
dialDown
dialUp
12 wipes/minute
leverDown
leverUp
High
20 wipes/minute
30 wipes/minute
60 wipes/minute
Unit Testing for Windshield Wiper Classes
• Can test only the Lever and Dial classes directly.
• Test cases to verify that event-oriented methods
make correct changes to the position attributes.
• Need “mock objects” (o-o analog of drivers for
procedural code) to provide inputs to test the wiper
class.
• Note how the “line” between unit and integration
testing is blurred!
Sample Unit Test Case for Lever
Test Case Name
Test Sense Up method
Test Case ID
Lever-1
Description
Verify that the LeverUp method correctly
changes the value of the position
attribute
Pre-Conditions
1. position = Off
Input(s)
Expected Output(s)
1. move lever to Int
2. position = Int
3. move lever to Low
4. position = Low
5. move lever to High
6. position = High
Post condition(s)
1. position = High
Test Result?
Pass/Fail
Test operator
Paul Jorgensen
Test Date
Dec. 8, 2013
Windshield Wiper StateChart
Lever
Wiper
Off
0 wipes/minute
leverDown
InState(Int)
leverUp
InState(Off)
Int
leverDown
InState(1)
leverUp
Low
leverDown
6 wipes/minute
InState(2)
InState(1)
leverUp
High
InState(2)
12 wipes/minute
InState(3)
Dial
1
dialUp
dialDown
2
dialUp
InState(3)
20 wipes/minute
InState(Low)
dialDown
InState(2)
InState(Int)
30 wipes/minute
InState(High)
InState(Low)
3
60 wipes/minute
StateChart-Based Testing for the
Windshield Wiper
• Need an engine to execute the StateChart
– execute “interesting” scenarios
– save paths as skeletons of system test cases
• The InState events show how the Wiper class can
be tested once the Lever and Dial classes have
been tested.
Sample System Level Test Case
Test Case Name
Exercise all wiper speeds
Test Case ID
WindshieldWiper-1
Description
The windshield wiper is in the OFF position, and the Dial is at
the 1 position; the user moves the lever to INT, and then moves
the dial first to 2 and then to 3; the user then moves the lever to
LOW.; the user moves the lever to High.
1. The Lever is in the OFF position
Pre-Conditions
2. The Dial is at the 1 position
3. The wiper speed is 0
Input events
Output events
1. move lever to INT
2. speed is 6
3. move dial to 2
4. speed is 12
5. move dial to 3
6. speed is 20
7. move lever to LOW
8. speed is 30
9. move lever to HIGH
10. speed is 60
1. The Lever is in the HIGH position
Post conditions
2. The Dial is at the 3 position
3. The wiper speed is 60
Polymorphism and Late Binding (in C++)
•
Polymorphism and late binding is a special feature that allows us to have
multiple behavior based on which class a statement is bound to. e.g. in C++
Class Cube{
protected:
float length;
public:
virtual float area( ) {return (length* length);} // area of square
void set_length(float z) {length = z} // set passed parameter, length
void volume( ) {cout<< “volume is” << area( ) * length;} // the area( ) method is not bound
};
Class Cylinder: public Cube
{
virtual float area( ) {return (3.14* length**2);} // area of circle
}
.
.
Cube c1, Cylinder cyl1;
.
c1.volume( ); // give us the volume of cube
cyl1.volume( ); // give us the volume of circle
•Both classes must be tested, especially if one of them is a division by length.
Polymorphism via dynamic instantiation (in JAVA)
class Shape { - - - - - - - }
class Rectangle extends Shape { - - - - }
class Triangle extends Shape { - - - - }
class Circle extends shape { - - - - }
import Rectangle;
import Triangle;
import Circle;
public class Example
{
public static void main ( String[ ] args)
String S = get_shape_type ( ) ; // some method that reads and returns a string to S
Shape myFigure;
myFigure = (Shape) java.lang.class.forName(S).newinstance( );
/* myFigure is instantiated to what the string read in --- hopefully it is rectangle, circle or triangle */
/* Note that it is “casted’ as type Shape, which is the parent Class */
}
Is equivalence class testing of valid vs invalid shape good enough?
Do you need to test everyone of the valid shape?
Polymorphism via “interface” (in JAVA)
public interface Speaker
{ --public void speak( );
}
public class cat implements Speaker
{ --public void speak ( )
{ system.out.println(“meow”); }
}
public class dog implements Speaker
{ --public void speak ( )
{ system.out.println(“woof woof”);}
}
Import cat;
Import dog;
Public class AnimalTalk
{ public static void main ( string[ ] arg)
{ Speaker current;
system.out.println(“enter 1 or 2”);
/* 1 = cat and 2 = dog */
int j = keyboard.readInt ( );
if (j == 1)
current = new cat ( );
else
current = new dog ( );
current.speak ( );
}
}
All Branch Test will take care of both cat and dog ?-----
Basic Levels of Testing in OO
Same as before;
testing the whole
system
System Test
Unit A
Integration test
Unit X
Integration test
Unit
Testing
Test relations
and
Inheritance;
Encapsulation;
Polymorphism
Test class
and
class Inheritance
Integration Testing
• Assumes the unit or units are unit-tested.
• Use the collaboration diagram and the
sequence diagram from UML to design the
integration test cases.
1
2
3
Collaboration diagram where
boxes are classes and numbered
arrows indicate sequenced
messages
Sequence diagram where the boxes
are classes and the arrows indicate
the sequence of messages
Testing Object-Oriented NextDate
•
•
•
•
Example—our familiar NextDate
Rewritten here in object-oriented style
One Abstract Class—CalendarUnit
Classes
–
–
–
–
–
testIt
Date
Day
Month
Year
• (See text for pseudo-code)
• Program graphs in next few slides
Program Graphs of Date Methods
testIt
Date.constructor
Date.increment
1
4
8
2
5
9
3
6
10
11
7
12
15
13
16
Date.printDate
19
20
14
17
18
Program Graphs of Day Methods
Day.constructor
Day.setDay
Day.increment
21
23
28
22
24
29
25
30
Day.setCurrentPos
Day.getDay
a
26
b
27
32
31
33
Program Graphs of Month Methods
Month.constructor
Month.setCurrentPos
Month.getMonth
34
a
39
35
b
40
Month.setMonth
Month.getMonthsize
boolean.increment
36
41
47
37
42
48
38
44
43
45
46
49
51
50
52
Program Graphs of Year Methods
Year.setCurrentPos
Year.constructor
Year.getYear
a
53
55
b
54
56
boolean.increment
boolean.isLeap
57
60
58
61
59
63
62
64
ooNextDate Collaboration Diagram
1. create
2. increment
3. getYear
Year
1. create
2. increment
3. getMonth
4. setMonth
1. create
2. increment
3. printDate
testIt
Month
Date
1. create
2. increment
3. getDay
4. setDay
Day
printDate Sequence Diagram
testIt
Date
.printDate
1. printDate
Day
d.setDay
Month
m.setMonth
2. setDay
3. setMonth
Time
4. setYear
Year
y.setYear
MM-Paths for O-O Software
• Definition: An object-oriented MM-Path is a
sequence of method executions linked by
messages.
• Call Graph slightly revised
– nodes are methods
– edges are messages
• Next three slides show sample Call Graphs for
ooNextDate
All MM-Paths as a Call Graph
Day
Day()
setCurrentPos()
msg6
increment()
msg16 msg15
testIt
Main
msg7
setDay()
getDay()
msg11
msg13
msg1
msg2
msg3
Month
Month()
Date
msg18
msg5
setCurrentPos()
msg17
getDate()
msg8
increment()
increment()
msg10
printDate()
msg12
msg19
setMonth()
getMonth()
getMonthSize()
msg4
Year
msg9
Year()
setCurrentPos()
msg14
increment()
setYear()
getYear()
msg21
msg20
MM-Path for January 3, 2013
Day
Day()
setCurrentPos()
msg6
increment()
msg16 msg15
testIt
setDay()
Main
getDay()
Month
msg1
Month()
Date
msg18
msg5
setCurrentPos()
getDate()
increment()
increment()
msg19
setMonth()
printDate()
getMonth()
getMonthSize()
msg4
Year
Year()
setCurrentPos()
increment()
setYear()
getYear()
msg21
MM-Path for April 30, 2013
Day
Day()
setCurrentPos()
increment()
testIt
Main
msg7
setDay()
getDay()
msg11
Month
Month()
msg2
Date
msg5
setCurrentPos()
getDate()
increment()
increment()
msg17
setMonth()
printDate()
getMonth()
getMonthSize()
msg4
Year
Year()
setCurrentPos()
increment()
setYear()
getYear()
msg20
Integration Test Coverage Metrics
• Coverage metrics with respect to Call Graph
• Given a set of test cases that
– covers each method (node coverage)
– covers each message (edge coverage)
– covers each path
System Testing for O-O Software
• Nearly equivalent to system testing for procedural
software.
• Some possibilities for sources of system test cases...
– Use cases
– Model-Based system testing
Second Example
(event-driven system testing)
Currency Converter
U.S. Dollar amount
Equivalent in ...
Brazil
Compute
Canada
Clear
European community
Japan
Quit
Second Example (continued)
label1
Currency Converter
frmCurrConv
label2
U.S. Dollar amount
txtDollar
label3
Equivalent in ...
lblEquivAmount
optBrazil
Brazil
optCanada
optEU
optJapan
Compute
cmdCompute
Canada
Clear
cmdClear
Quit
cmdQuit
European community
Japan
Input Events for the Currency Converter
Input Events
Input Events
ip1
Enter US Dollar amount
ip2.4
Click on Japan
ip2
Click on a country button
ip3
Click on Compute button
ip2.1
Click on Brazil
ip4
Click on Clear button
ip2.2
Click on Canada
ip5
Click on Quit button
ip2.3
Click on European
Community
ip6
Click on OK in error
message
Output Events for the Currency Converter
Output Events
Output Events
op1
Display US Dollar Amount
op4
Reset selected country
op2
Display currency name
op4.1
Reset Brazil
op2.1
Display Brazilian Reals
op4.2
Reset Canada
op2.2
Display Canadian Dollars
op4.3
Reset European Community
op2.3
Display European Community Euros
op4.4
Reset Japan
op2.4
Display Japanese Yen
op5
Display foreign currency value
op2.5
Display ellipsis
op6
Error Msg: Must select a country
op3
Indicate selected country
op7
Error Msg: Must enter US Dollar
amount
op3.1
Indicate Brazil
op8
Error Msg: Must select a country and
enter US Dollar amount
op3.2
Indicate Canada
op9
Reset US Dollar Amount
op3.3
Indicate European Community
op10
Reset equivalent currency amount
op3.4
Indicate Japan
StateChart for the Currency Converter
In Storage
ip 5 Quit
Executing
End Application
Ip 4
Idle
Ip4
___________________
op 2, op 4, op 9 , op 10
Ip 3/op 8
GUI action
Ip 2/ op 2 ,op 3
Country Selected
Ip 6
Ip 1/op 1
U .S. Dollar Amount Selected
Missing Country and Dollar Message
Ip 1/op 1
Ip 2/op 2,op 3
Ip 3/op 7
Ip6
Ip 6
Both Inputs Done
Missing U .S. Dollar Message
Missing Country Message
Ip 3/op 5
Ip1 /op 1
Ip 2/op 2,op 3
Equiv . Amount Displayed
Ip 3/ op 7
Sample System Level Test Case
System test Case -3
Normal usage (dollar amount entered first)
Test performed by
Paul Jorgensen
Pre-Conditions
txtDollar has focus
Input events
Output events
1. Enter 10 on the keyboard
2. Observe 10 appears in txtDollar
3. Click on optEU button
5.Click cmdCompute button
4. Observe “euros” appears in label3
6. Observe “7.60” appears in lblEquivAmount
Post-Conditions
cmdClear has focus
Test result
Pass (on first attempt)
Date run
May 27, 2013
Download