Title: 8' UNIT TESTING
18. UNIT TESTING
2Software Engineering Roadmap Chapter 8 Focus
Identify corporate practices
Test units (parts) separately - use
implementations - apply discipline - gain
coverage
Plan project
Analyze requirements
Maintain
Integrate test system
Design
Test units
Implement
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
3Learning Goals of This Chapter
- Understand meaning of unit testing
- Distinguish black box vs. white box testing
- Attain proper test coverage
- Learn a testing standard
- Inspect a unit test plan
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
41. Introduction to unit testing
5Golden Rules of Testing
- Goal of testing maximize the number and severity
of defects found per dollar spent - thus test early
6Golden Rules of Testing
- Goal of testing maximize the number and severity
of defects found per dollar spent - thus test early
- Limits of testing Testing can only determine the
presence of defects, never their absence - use proofs of correctness to establish absence
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
7Testing the Big Picture
3. System tests
2. Integration tests
Module combination
1. Unit tests
Module
Function
8Testing the Big Picture
3. System tests
Include use-cases
2. Integration tests
OO
Packages of classes
Module combination
1. Unit tests
Combinations of methods in class
Module
Methods
Function
9Unified Process
Jacobson et al USDP
Elaboration
Inception
Construction
Transition
Requirements Analysis Design Implemen- ta
tion Test
Prelim. iterations
Iter. 1
Iter. n
Iter. n1
Iter. m
Iter. m1
Iter. k
..
10Unified Process
Jacobson et al USDP
Elaboration
Inception
Construction
Transition
Requirements Analysis Design Implemen- ta
tion Test
Unit Tests
Integration tests ... System tests
Prelim. iterations
Iter. 1
Iter. n
Iter. n1
Iter. m
Iter. m1
Iter. k
..
..
11RoadMap for Unit Testing
Requirements
1. Plan for unit testing -- see section SSS
Detailed design
. . . .
Test results
12RoadMap for Unit Testing
Requirements
1. Plan for unit testing -- see section SSS
Identify largest trouble spots
Detailed design
Unit test plan
2. Acquire test set -- see section SSS
Products of prior testing
Test set
3. Execute unit test -- see section SSS
Test results
Code under test
IEEE, 1986
132. Test types
14Black-, Gray-, White-box Testing
Input determined by...
Result
Actual output compared with required
Black box
requirements
from previous phase
15Black-, Gray-, White-box Testing
Input determined by...
Result
Actual output compared with required output
Black box
requirements
Gray box
As for black- and white box testing
requirements key design elements
White box
Confirmation of expected behavior
design elements
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
16Test Input Possibilities
Infinitely many illegal values choose a finite
sample.
principal
100
100M
20
Infinitely many legal values choose a finite
sample.
inflation estimate
25
interest rate
1
0
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
17Test Input Partitioning and Boundaries
An illegal region
principal
Boundaries
100
100M
20
inflation estimate
Range of valid inputs
25
interest rate
1
0
Equivalence partitions
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
18Testing Ranges Elementary Cases
- 1. within range
- 2. at the boundaries
- of the range
- 3. outside the range
- (illegal)
range
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
19Covering Every Statement is Not Sufficient (Myers)
Required program
ugt1 and v0
Yes
x x/u
No
u2 or xgt0
Yes
x
No
20Covering Every Statement is Not Sufficient (Myers)
- Code attempt to implement flowchart
- if( (ugt1) (v0) ) (1)
- x x/u (2)
- if( (u2) (xgt3) ) (3)
- x (4)
- u2, v0 and x3
- executes every line (1) - (4)
- gives the correct output x 2.5
-
- However, line (3) is wrong
Required program
ugt1 and v0
Yes
x x/u
No
u2 or xgt0
Yes
x
No
21Paths to be Checked
Parameter settings make sense?
N
Y
Set _name to defaultName"
Parameter name too long?
Y
N
Truncate name
Set _name to parameter
22Paths to be Checked
Parameter settings make sense?
N
Y
Set _name to defaultName"
Parameter name too long?
Y
N
Decision Coverage
Truncate name
Set _name to parameter
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
23Assertion-based testing for max() 1/2
public static boolean checkAssertion ( int
loopSoFarP, int indexOfMaxP, double arrayP )
// First establish following
booleans boolean b1M true / means values
of arrayP are lower than arrayP
indexOfMaxP for all indices lt indexOfMaxP
/ if( indexOfMaxP ! 0 ) // b1M true if max so
far is first element for( int u 0 u lt
indexOfMaxP u ) b1M ( arrayPu lt
arrayP indexOfMaxP ) . . . .
Defining the assertion checker
24Assertion-based Testing for max()
public static boolean checkAssertion ( int
loopSoFarP, int indexOfMaxP, double arrayP )
// First establish following
booleans boolean b1M true / means values
of arrayP are lower than arrayP
indexOfMaxP for all indices lt indexOfMaxP
/ if( indexOfMaxP ! 0 ) // b1M true if max so
far is first element for( int u 0 u lt
indexOfMaxP u ) b1M ( arrayPu lt
arrayP indexOfMaxP ) boolean b2M true /
means vals. of arrayP no higher than
arrayP indexOfMaxP for indices indexOfMaxP
loopSoFarP / for( int v indexOfMaxP v lt
loopSoFarP v ) b2M ( arrayPv lt arrayP
indexOfMaxP )
Defining an Assertion Checker 1 of 2
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
25Defining an Assertion Checker for max() 2 of 2
if ( // Loop has progressed up to index
loopSoFarP ( 0 lt loopSoFarP ) (loopSoFarP lt
arrayP.length ) // indexOfMaxP is the index
lt loopSoFarP ... ( 0 lt indexOfMaxP ) (
indexOfMaxP lt loopSoFarP ) b1M b2M //
... where the first max occurs ) System.out.pr
intln( "Assertion valid" ) return
true else System.out.println( "Assertion
invalid" ) return false
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
26Applying Assertion-basedtesting to max()
/ Finds index value of first of the largest
array elements ... / public static void
main( String mainArg ) double a
getArray() // Let I be the assertion (see
section tbd of chapter 7) ... Establish I int
i 0 int k 0 boolean validityM
checkAssertion( i, k, a ) // assertion
test // Following preserves I . terminates
. (section tbd of chapter 7) while( i !
a.length - 1 ) i if( ai gt ak ) k
i validityM validityM checkAssertion(
i, k, a ) // assertion test
System.out.println( "First max value is "
ak " at index " k ) System.out.println(
"Validity " validityM ) // assertion
report
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
273. Planning unit tests
28Plan for Unit Testing
One way to ...
- 1. Decide on the philosophy for unit testing
- individual engineer responsible (common)?
- reviewed by others?
- designed performed by others?
- 2. Decide what / where / how to document
- individuals personal document set (common)?
- how / when to incorporate into other types of
testing? - incorporate in formal documents?
- use tools / test utilities?
- 3. Determine extent of unit testing (i.e., in
advance). - do not just test until time expires
- prioritize, so that important tests definitely
performed - 4. Decide how and where to get the test input
- see section tbd.
- 5. Estimate the resources required
- use historical data if available
- 6. Arrange to track time, defect count, type
source
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
294. Checklists and examples for method testing
30Perform Method Testing (Humphrey) 1/2
One way to ...
1. Verify operation at normal parameter values
(a black box test based on the units
requirements) 2. Verify operation at limit
parameter values (black box) 3. Verify
operation outside parameter values (black box)
4. Ensure that all instructions execute
(statement coverage) 5. Check all paths,
including both sides of all branches (decision
coverage) 6. Check the use of all called
objects 7. Verify the handling of all data
structures 8. Verify the handling of all files
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
31Perform Method Testing (Humphrey) 2/2
One way to ...
9. Check normal termination of all loops (part
of a correctness proof) 10. Check abnormal
termination of all loops 11. Check normal
termination of all recursions 12. Check abnormal
termination of all recursions 13. Verify the
handling of all error conditions 14. Check timing
and synchronization 15. Verify all hardware
dependencies
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
324. Checklists and examples for method testing
33Relating Tests to Requirements Design
(2) Design GameCharacter Requirements An abstract
class with attribute name ...
(1) D-Requirements 3.2.EC.1.2 Qualities of
Encounter characters Every game character has the
same set of qualities. Each quality shall be a
non-negative floating point number with at least
one decimal of precision. . . .
. . . .
34Relating Tests to Requirements Design
(2) Design GameCharacter Requirements An abstract
class with attribute name ...
(1) D-Requirements 3.2.EC.1.2 Qualities of
Encounter characters Every game character has the
same set of qualities. Each quality shall be a
non-negative floating point number with at least
one decimal of precision. . . .
Test this class ...
... against this requirement
Characters
GameCharacter
Test this method ...
Encounter Characters
... against this requirement
EncounterCharacter adjustQuality()
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
35Partitioning of Range for Unit Testing 1 of 2
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
36Partitioning of Range for Unit Testing 2 of 2
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
375. Checklists and examples for class testing
38Perform ClassUnit Tests
One way to ...
- 1. Exercise methods in combination
- 2-5, usually
- choose most common sequences first
- include sequences likely to cause defects
- requires hand-computing the resulting attribute
values - 2. Focus unit tests on each attribute
- initialize, then execute method sequences that
affect it - 3. Verify that each class invariant is
unchanged - verify that the invariant is true with initial
values - execute a sequence (e.g., the same as in 1.)
- verify that the invariant still true
- 4. Verify that objects transition among expected
states - plan the state / transition event sequence
- set up the object in the initial state by setting
variables - provide first event check that transition
occurred . etc.
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
39Encounter State-Transition Test Sequence 1 of 2
test step 1
Preparing
Verify that the game is initially in Preparing
state (by checking on the class membership of
gameStateI)
Player dismisses qualities menu
Waiting
40Encounter State-Transition Test Sequence 1 of 2
test step 1
test step 2
Preparing
Verify that the game is initially in Preparing
state (by checking on the class membership of
gameStateI)
Dismiss the quality menu, and verify that the
game is in Waiting state.
Player dismisses qualities menu
test step 3
Move the player character to an adjacent area,
and verify that the game is still in Waiting
state.
Waiting
Move to adjacent area
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
41Complete Encounter State-Transition Test
1
2
Preparing
Player dismisses qualities menu
Reporting
Player dismisses encounter report menu
6
3
5
Waiting
Encounter completed
Move to adjacent area
4
Character enters area inhabited by an opponent
Engaging
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
426. Summary
43Unit Testing Summary
- Unit testing ? pieces
- Other testing ? assemblies
- Black box input / output only
- White box verifies processing
- Several ways
- Ensure completeness
- Test planning earlier / better
- helps clarify requirements
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
44Case StudyEncounterCharacter.java
45Listing page 1
/ To test this class. _at_param argsP destinati
on of method test log, class test log
respectively / public static void main( String
argsP ) // Default files on which to write
test output run tests String
methodOutputFileNameM "methodOutput.txt" Strin
g classOutputFileNameM "classOutput.txt" if(
argsP ! null argsP.length 2 ) // use
defaults if input improper methodOutputFileNam
eM argsP0 classOutputFileNameM
argsP1 // 1. EXECUTE TESTS WHICH DO NOT
REQUIRE HUMAN INTERVENTION // Test methods
individually, then test class try
testEncounterCharacterMethods(
methodOutputFileNameM ) testEncounterCharacterC
lass( classOutputFileNameM ) catch(
IOException eP ) System.out.println( eP )
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
46Listing page 2
// 2. EXECUTE TESTS WHICH DO REQUIRE HUMAN
INTERVENTION Frame imageTests //
Display test cases. new testCharacterImage(
// Missing image. new
EncounterCharacter( "GuyWithNoImage", null ) ),
new testCharacterImage( // Image is
present. new EncounterCharacter(
"Elena", "elena.gif" ) ) for( int i 0 i
lt imageTests.length i) // Display each
test window. imageTestsi.setSize(400,
250) // Adequate size for character.
imageTestsi.setVisible(true)
imageTestsi.show() try //
Let user examine windows.
Thread.currentThread().sleep( 301000 )
catch( Exception exc ) for( int i
0 i lt imageTests.length i ) // Shut the
windows. imageTestsi.dispose() System.
exit( 0 )
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
47Listing page 3
/ Tests this class by executing its methods in
combination. _at_param destinationP Location to
write results. _at_exception IOException If
theres a problem opening or accessing
destinationP / public static void
testEncounterCharacterClass( String destinationP
) throws IOException / Prepare for the
test / PrintWriter outM new PrintWriter( new
FileOutputStream( destinationP )
) System.out.println( "\nEncounterCharacter
class test results on " destinationP "\n"
) / The following methods will be tested
in sequences a. adjustQuality( String
qualityP, float qualityValueP ) d.
deleteFromEncounterCharacters( EncounterCharacter
encounterCharacterP ) ge.
EncounterCharacter getEncounterCharacter( String
nameP ) gq. float getQualityValue( String
qualityP ) gt. float getTolerance()
io. int indexOf( String qualityP ) ii.
insertIntoEncounterCharacters(
EncounterCharacter encounterCharacterP ) m.
int maxNumCharsInName() sq. setQuality(
String qualityP, float qualityValueP ) so.
float sumOfQualities()
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
48Listing page 4
The following sequences occur
commonly ge-aq-so ge-sq-a-gq
. . . . . The following sequences have a
high potential for defects
ge-aq-aq-gq-so . . . . . / / Test
C1 ge-aq-so / EncounterCharacter eC1M new
EncounterCharacter( "CharForTestC1" ) // method
ge eC1M.adjustQuality(QUAL_STRENGTH, 40.0f
) // aq TestExecution.printReportToFile(
outM, "Class test ge-aq-so",
eC1M.sumOfQualities(), 100.0f ) // so /
Test C2 ge-aq-aq-gq-so / EncounterCharacter
eC2M new EncounterCharacter( "CharForTestC2" )
// ge eC2M.adjustQuality(QUAL_STRENGTH, 40.0f
) // aq eC2M.adjustQuality(QUAL_STAMINA,
20.9876f ) // aq
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
49Listing page 5
TestExecution.printReportToFile( outM, "Class
test ge-aq-aq-gq-so part 1", eC2M.getQualityVal
ue( QUAL_STAMINA ), 20.9876f ) //
gq TestExecution.printReportToFile( outM,
"Class test ge-aq-aq-gq-so part 2",
eC2M.sumOfQualities(), 100.0f ) // so /
INVARIANT-ORIENTED TESTS Check for the
invariant qualValueIi gt0 -- after
executing the sequences of methods executed
above / boolean truthM true for( int i
0 i lt qualityTypeS.length i ) / Set
truthM false if any entry in eC1M.qualValueI not
gt 0 / truthM truthM ( eC1M.qualValueIi
gt 0.0f ) TestExecution.printReportToFile(
outM, "Class test for the invariant
'qualValueIi gt0'", truthM, true ) /
Conclude / outM.close() System.out.println(
"\nClass tests of EncounterChar class concluded."
) // end of testEncounterCharacterClass
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
50Listing page 6
/ Tests all the methods of this class one at a
time _at_param destinationP Location to write
results. _at_exception IOException If theres a
problem opening or accessing destinationP / publi
c static void testEncounterCharacterMethods(
String destinationP ) throws IOException /
Prepare for the test / FileWriter outM new
FileWriter( new File( destinationP )
) System.out.println( "EncounterCharacter
method test results on " destinationP "\n"
) / Tests for getEncounterCharacter()
/ EncounterCharacter eCNorM new
EncounterCharacter( "qwerty" ) // normal
TestExecution.reportToFile( outM,
"GetCharacter Test 1 nominal value",
eCNorM.getName(), "qwerty" ) EncounterCharacte
r eCNullM new EncounterCharacter( null )
// null TestExecution.reportToFile( outM,
"GetCharacter Test 2 null parameter",
eCNullM.getName(), GameCharacter.
DEFAULT_NAME)
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
51Listing page 7
String tooLongM "123456789012345678901234567890
1234567890" EncounterCharacter eCTooLongM
new EncounterCharacter(tooLongM) // too long
TestExecution.reportToFile( outM, "GetCharacter
Test 3 Limit parameter values, " "max name
len " eCTooLongM .maxNumCharsInName(),
eCTooLongM.getName(), tooLongM.substring(0,
eCTooLongM.maxNumCharsInName())
) EncounterCharacter eCZeroM new
EncounterCharacter( "" ) // zero-len
TestExecution.reportToFile( outM,
"GetCharacter Test 4 zero-length", eCZeroM
.getName(), GameCharacter. DEFAULT_NAME) Encou
nterCharacter eCPuncM new EncounterCharacter(
"ab" ) // bad chars TestExecution.reportToF
ile( outM, "GetCharacter Test 5 bad char '' ",
eCPuncM .getName(), GameCharacter.
DEFAULT_NAME)
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
52Listing page 8
/ Tests for indexOf() for every valid quality
name. / for( int i 0 i lt qualityTypeS.length
i ) try TestExecution.reportToFile( outM,
"indexOf() Test 1." i " valid name "
qualityTypeSi, indexOf(qualityTypeSi), i
) catch( Exception eP )
TestExecution.reportToFile( outM, "indexOf() Test
1 valid name compare ", "indexOf('"
qualityTypeSi "')", "with expected " i )
/ Tests for indexOf() for an invalid
quality name. / try TestExecution.reportToFile
( outM, "indexOf() Test 2 invalid name
zorch", indexOf("zorch"), -1 ) catch(
Exception eP ) TestExecution.reportToFile(
outM, "indexOf() Test 2 valid name compare
", "indexOf(\"zorch\")", "with expected -1" )
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
53Listing page 9
/ Tests for setQuality() / // Set up for
test EncounterCharacter hank new
EncounterCharacter( "Hank" ) // Nominal
value hank.setQuality(QUAL_STRENGTH , 10.3f
) TestExecution.reportToFile( outM,
"setQuality() Test 1 nominal value",
hank.getQualityValue( QUAL_STRENGTH ), 10.3f
) // Out of range value hank.setQuality(
QUAL_PATIENCE, -6.2f ) TestExecution.reportToFi
le( outM, "setQuality() Test 2 nominal value",
hank.getQualityValue(QUAL_PATIENCE ), 0.0f )
// Value below close-to-zero
threshold. hank.setQuality( QUAL_STAMINA,
getTolerance() 0.9f ) TestExecution.reportToF
ile( outM, "setQuality() Test 3 value close to
zero", hank.getQualityValue(QUAL_STAMINA),
0.0f )
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
54Listingpage 10
// Tests for adjustQuality(). // Set up for
test and verify Values should be 20
each. EncounterCharacter harvey new
EncounterCharacter( "Harvey" )
TestExecution.reportToFile( outM,
"adjustQuality() test 0 verify that values add
to 100", harvey.sumOfQualities(), 100.0f
) // Nominal adjustment harvey.adjustQua
lity(QUAL_STRENGTH , 30.0f ) // strength 30
rest 70/4 each TestExecution.reportToFile( outM,
"adjustQuality() test 1 values sum to 100 after
adjusting", harvey.sumOfQualities(), 100.0f
) TestExecution.reportToFile ( outM,
"adjustQuality() test 2 values adjusted as
commanded", harvey.getQualityValue(QUAL_STREN
GTH ), 30.0f ) // Adjustment resulting in a
zero value harvey.adjustQuality( QUAL_STAMINA,
99.0f ) TestExecution.reportToFile( outM,
"adjustQuality() test 3 verify low value reverts
to zero", harvey.getQualityValue(
QUAL_STRENGTH ), 0.0f ) // Conclude
outM.close() System.out.println( "\nMethod
tests of EncounterCharacter class concluded." )
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
55Listing page 11
/ Class to test repainting of characters.
Creates a window, which will contain several
copies of the character image. / private static
class testCharacterImage extends Frame /
Instance attribute that remembers which character
image to display. / private EncounterCharacter
characterI / Basic constructor -- create
a window for testing some character's image.
_at_param characterP Character whose image is to be
tested. / testCharacterImage(EncounterCharacter
characterP) super(characterP.getName()) //
Do all normal Frame initialization.
characterI characterP // Remember which
character we're testing.
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 20001), with permission.
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 20001), with permission.
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 20001), with permission.
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 20001), with permission.
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 20001), with permission.
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.
56Listing page 12
/ Repaint the display areaof the frame.
_at_param drawP Graphics context for drawing the
character. / public void paint(Graphics
drawP) Dimension frameSizeM getSize() //
Size of the window area. int widthUnitM
frameSizeM.width / 5 // Convenient divisions
of window. int heightUnitM
frameSizeM.height / 5
characterI.showCharacter(this, drawP, //
Drawn small, facing right. new
Point(widthUnitM, heightUnitM), heightUnitM,
false) characterI.showChara
cter(this, drawP, // Drawn large, facing
left. new Point(widthUnitM4, heightUnitM3),
heightUnitM2, true)
characterI.showCharacter(this, drawP, //
Drawn large, facing right. new
Point(widthUnitM2, heightUnitM2),
heightUnitM2, false)
characterI.showCharacter(this, drawP, //
Drawn small, facing left. new
Point(widthUnitM3, heightUnitM4), heightUnitM,
true) // End of testCharacterImage
inner class
Adapted from Software Engineering An
Object-Oriented Perspective by Eric J. Braude
(Wiley 2001), with permission.