Issues in Testing Object Orientated Systems - Swanseacsmarkus/CS339/dissertations/GawnJ.pdfIssues in...

26
Issues in Testing Object Orientated Systems James Gawn 329338 January 12, 2007 Abstract In this document you will find an overview of the object orientated paradigm and how implementing software with the paradigm affects the testing process. This will include discussing the issues surrounding inheritance, polymorphism as well the different levels of testing. 1

Transcript of Issues in Testing Object Orientated Systems - Swanseacsmarkus/CS339/dissertations/GawnJ.pdfIssues in...

Issues in Testing Object Orientated Systems

James Gawn

329338

January 12, 2007

Abstract

In this document you will find an overview of the object orientated

paradigm and how implementing software with the paradigm affects

the testing process. This will include discussing the issues surrounding

inheritance, polymorphism as well the different levels of testing.

1

Issues in Testing Object Orientated Systems – James Gawn 2

Contents

1 Introduction 3

1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.2.1 Functional Testing . . . . . . . . . . . . . . . . . . . . 41.2.2 Structural Testing . . . . . . . . . . . . . . . . . . . . . 5

2 The Object Orientated Paradigm 6

2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.2 The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.3 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.4 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.4.1 Basics of Inheritance . . . . . . . . . . . . . . . . . . . 92.4.2 Composite Inheritance . . . . . . . . . . . . . . . . . . 112.4.3 Multiple Inheritance . . . . . . . . . . . . . . . . . . . 12

2.5 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3 Testing Levels for Object Orientated Systems 15

3.1 Introducting Testing Levels . . . . . . . . . . . . . . . . . . . 153.2 Method Level . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.3 Class Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.4 Integration Level . . . . . . . . . . . . . . . . . . . . . . . . . 173.5 System Level . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

4 Testing Object Orientated Systems 19

4.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194.2 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . 194.3 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

4.3.1 Class Flattening . . . . . . . . . . . . . . . . . . . . . . 224.4 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5 Summary 25

5.1 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255.2 Futher Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Issues in Testing Object Orientated Systems – James Gawn 3

1 Introduction

The area of software testing is important one in software development, justas it is important for an engineer to ensure that a bridge will not fall down,or a building will not collapse. It is not only important to make sure thatyou don’t have potentially fatal errors such as a building falling down, butalso ensuring that any system that is developed actually performs correctlythe task for which it is designed. In this document an overview of the effectsin using the object orientated paradigm during the software developmentprocess with the focus being on the testing element.

In order to get a full understanding of the issues that will be discussedan understanding of the paradigm itself will be needed as such the firstsection of this document includes an object orientated introduction. Thisthen continues into a section that outlines the different levels of testing duringthe development process, when using this model. Further to this the nextsection then goes into further detail into the various aspects of the objectorientated system and how each of these in turn present their own individualchallenges and opportunities when performing testing.

Finally the document is finished off with a summary of the importantaspects, as well as a look into the study that can be further made into thearea.

1.1 Motivation

The motivation of this document is to provide the reader with a basic un-derstanding of the testing issues that arise when dealing with the objectorientated paradigm. Th6is is ever more important when you bare in mindthe growing in popularity in using languages such as Java, C++, as well as agrowing number of others which all make use of object orientated techniques.This combined with the fact that there are some significant issues that needto be address when working within it, make it important to at least considerand understand these in order to perform suitable levels of testing.

1.2 Testing

This chapter will outline some of the basic testing terms that are usedthroughout this paper. This will then provide some background knowledgeof testing to facilitate understanding of various points that are made later.

Issues in Testing Object Orientated Systems – James Gawn 4

First you have to define what it is testing is trying to achieve, and simplyput it is ensuring that the an implementation matches a given specification.This therefore implicitly requires that a detailed specification of a system iscreated in order to allow effective testing. The next step being the creation ofa variety of test cases, which are sets of inputs which then are matched with aset of expected outputs (based on the mentioned specification). Therefore oneof the main goals in testing is to find suitable ways to generate or create waysof finding test cases that as far as possible are able to identify errors (wherean error is a mistake made during the implementation of a specification) andto prevent faults. Faults are key in testing, these being the actual realisationof an error during the running of a system.

There are two distinct ways which have emerged to perform testing, withthese being the functional and structural methods. It should be noted thatneither of these is better than the other and both can be used to find testcases, although they often both are better at finding different types of errors.

1.2.1 Functional Testing

The first of these testing methods being functional, which relates to thegeneration of test cases solely based on the inputs and outputs of a givenprogram without any regard for the manner in which the interior of the pro-gram operates. Of course this is very dependant on an acurate specification,if any part of a specification is incorrect it would be impossible to find anyerrors. It can be noted that this style of testing can often also be comparedwith the idea of blackbox testing [4, P7].

This method has a number of downfalls if used without the second method,the main one being that it can be impossible to find undocumented interfacesand features. This is simply because you pay no attention to the actual code,but rather, just the inputs and outputs of the known features, and thereforewould be impossible for these to be found.

This downfall of functional testing can provide to be very troublesome, ifstart by considering a program written in java that stores passwords for you.Now if you then receive this program, and perform your functional testingon it, and it seems to be secure, so you start using it. If you then considerthat the person who created the program was malicious in nature so theyput an extra function into the program which was not specified by you thatreturns all the passwords without authentication, this would not be able tobe found simply because it is not in the specification.

Issues in Testing Object Orientated Systems – James Gawn 5

So a more tangible example of this might be if you are testing a lightswitch, in functional testing you might test to ensure that the light switchturns on if you press it, and then turns off when you press it again. Thoughyou would not then open the light switch up to make sure that when youperform the various operations the circuitry inside is performing as you wouldexpect.

1.2.2 Structural Testing

The second of the methods of testing is structure testing which focuses ratherless on the actual specification but rather more on the implementation andprogramming code. This type of testing is also sometimes referred to aswhite box testing[4, P8].

The main focus of structural testing is often a number of test coveragemetrics[1, P324], and by this it is meant the quantity of the code that hasbeen executed during a test suite (where a test suite is a collection of testcases). This is achieved by performing detailed analysis on the source codeto find a suitable level of coverage for the particualar programs purposes.

There are like with functional testing a number of limitations if used asthe sole way of testing a system, the most prominent of these being the mostobvious which is testing for the absence of features. Due to the detachmentfrom comparing the specification and the implementation you would be un-able to find features that are missing, and in fact as a whole structural testingwill only show that an implementation does what it intends but not what itis actually meant to be be achieving.

Again if we consider the simplistic light switch example that was providedpreviously, in structural testing you might open up the light switch andmeasuring the voltage on the different wires within the switch while turningit on and off, to ensure that all the different wires have the expected voltages.

Issues in Testing Object Orientated Systems – James Gawn 6

2 The Object Orientated Paradigm

2.1 Introduction

The first step in understanding the issues surrounding testing of systemsprogrammed using the object orientated paradigm is to get an understandingof the paradigm itself. This can then give us the some of the building blocksrequired to properly understand the issues that affect testing these types ofsystems.

Within this section some of the features of object orientated paradigmare discussed, as well as how that these differ from traditional proceduralprogramming. This will include an overview of the concepts of encapsulation,the different approaches to inheritance, as well as polymorphism.

As well as discussing the differences I also plan to draw some parallelsbetween existing languages, and the methodologies used in object orientatedlanguages.

2.2 The Basics

The basis for the object orientated paradigm is by using the more modernapproaches to data abstraction you eventually come across the concept ofabstract types or classes. In object orientated programming we use theseclasses and introduce the concepts of hierarchies.

These classes then define the characteristics of the objects within a sys-tem, where these objects are simply a set of variables with a number ofmethods (or sometimes called functions) that are associated with them; withthese methods allowing the manipulation of the data that is stored in thesevariables. It is often the case with these objects that the variables themselvesare not accessible directly from outside the object without accessing themthrough the methods. If you now take this a step further and you populatethe variables with values then you can consider that an object is an instan-tiation of a class. This process is often performed by a constructor whichis often thought of as a special method that initialises or creates the objectbased on the class. These classes of objects can then be composed togetherto create series of co-operating objects that work together to make a wholesystem.

These objects can then provide a way to model a real world system orenvironment as collections of virtual entities in a simple way. If you consider

Issues in Testing Object Orientated Systems – James Gawn 7

an object for example a radio, it may have a large number of states based on anumber of different settings. If you take these setting on the radio and makethese variables in an object, for instance if the radio is on or off could be avariable within a radio object, or the frequency currently tuned to. But thenif you consider the methods used to change the frequency currently tuned, ifthe radio has some constraints, maybe you can’t got above or below certainfrequency’s this can be enforced onto this object model through the methods.This can provide a reliable way to ensure that the model (when testing to itworks as intended of course) can never enter an invalid state simple becausethe variable is not directly accessed but is changed by methods which theobject has.

There are a number of key components that will be discussed in the nextfew sections which are used to construct object orientated languages. Furtherthan just the idea of having classes of objects, the concepts of encapsulation(touched on already), inheritance, and polymorphism are important.

2.3 Encapsulation

The concept of encapsulation is not exclusively for the object orientatedparadigm, and in fact, it is not even essential to it; although it is so often usedin object orientated languages so it is important to make sure its implicationsin testing are understood, hence this section.

The concept of encapsulation have been in use for some time with nonobject orientated languages, for example in ADA packages [2, P137], althoughthis is not in the scope of this document it is important to note that thetesting issues related with encapsulation can be relevent for these languagesas well as object orientated ones.

The general idea of encapsulation in object orientated system is to onlymake certain methods and/or variables from within an object visible to ob-jects externally. This gives rise to the idea of public and private methods andvariables. This is where public methods are invokable by other objects as wellas the object in question, and public variables are accessible and modifiableby other objects as well as the source object. Private methods and variableson the other hand are strictly accessable only by the object itself, and arenot accessable externally unless through some other methods. For example itis often deamed good practice with object orinetated programming to makevariables private and mediate access to them always with accessor methods,or in other words have public methods to set and return the contents of

Issues in Testing Object Orientated Systems – James Gawn 8

the private variable. In essence encapsulation is an access control systemfor objects, enabling objects to provide some kind of limited interface to itsfunctionality without bearing all of its inner workings to other objects.

A simplistic abstract example of this could be a ticket system, considerthat it has a certain number of tickets that it can give out before it runsout. Now someone accessing the system simply needs to know if it is able todispense a ticket or not, but does not need to know how many tickets thereare, or even how many are left, just that they are able to get one ticket (SeeJava code example 1).

Listing 1: A Simple Ticket Dispenser

pub l i c c l a s s TicketDispenser {

pr i va t e i n t numberOfTickets ;p r i va t e i n t numberOfTicketsDispensed ;

// Creates a t i c k e t d i sp en s e r with a no o f t i c k e t s .pub l i c TicketDispenser ( i n t numberOfTickets ) {

t h i s . numberOfTickets = numberOfTickets ;numberOfTicketsDispensed = 0 ;

}

//Returns i f t i c k e t s a v a i l a b l e .pub l i c boolean r e turnTicke t sAva i l ab l e ( ) {

i f ( numberOfTicketsDispensed <

numberOfTickets ) {return true ;

} e l s e {return f a l s e ;

}}

// Pr in t s a t i c k e t i f any a va i l a b l e .pub l i c boolean pr in tT i cke t ( ) {

i f ( r e tu rnTicke t sAva i l ab l e ( ) ) {numberOfTicketsDispensed++;

Issues in Testing Object Orientated Systems – James Gawn 9

return true ;} e l s e {

return f a l s e ;}

}

}

As you can see in the preceding example, both the fields that hold theinformation about the number of tickets and tickets available are set to pri-vate. This is encapsulating this information so that is only accessible by thisclass, but this idea of encapsulation is not just limited to the variables. It isperfectly possible that you have a method that is private, in fact you couldin this example make the ”returnTicketsAvailable” method private, so thatthe ticket machine simply prints a ticket if there is one available but someoneis unable to query in advance if a ticket is available.

In fact the concept of encapsulating methods can be a useful one, if youhave a method that performs some complex task it is often useful to beable to break this down into a number of distinct methods. Although youdon’t want the external entity to have to call each of these methods in turnto perform the task, so if you make all these building block methods privateand have just one public method taking the inputs require for all the methodsthen you get a simpler interface.

2.4 Inheritance

2.4.1 Basics of Inheritance

In contrast to encapsulation inheritance is one of the foundations of theobject orientated paradigm, the basics for this idea is one class is able toinherit/extend the functionality of another class. This gives rise to the ideasof a superclass as well as a subclass, where a superclass refers to the classwhich a another class is inheriting from, and where this inheriting class asubclass.

So if you continue the example of the ticket machine from the previousexample, suppose that you now want to construct a more sofisticated ticket

Issues in Testing Object Orientated Systems – James Gawn 10

machine. Rather than starting from scratch you can simply extend the newticket machine by the old one and add the new functionality that you require.In this example the ticket machine now can be queried to find out how manytickets are remaining:

Listing 2: An Improved Ticket Dispenser

pub l i c c l a s s NewTicketDispenser extendsTicketDispenser {

pub l i c NewTicketDispenser ( i n tnumberOfTickets ) {

super ( numberOfTickets ) ;}

pub l i c i n t returnNoOfTicket sAva i lab le ( ) {return numberOfTickets −

numberOfTicketsDispensed ;}

}

If you notice in this example it is making use of variables that are con-tained within the superclass, now if you bare in mind the concepts of encap-sulation that were stated earlier these might not necessarily be accessible.The variable can sometimes be accessible but this is not always the case anddepends on the programming languages implementation of the paradigm. Itis often the case that a different modifier is used in order to allow accessto variables by subclasses; and this modifier can then be used in place ofthe ”private” modifier. In many languages this is often called a ”protected”variable.

It is also possible for a subclass to inherit a method from a superclassbut then actually override it (so called method overridding), this can be for anumber of reasons but is often just to provide a more specialised method toachieve a similar task. So again continuing with the improved ticket dispenserexample, if you would like to make it so the new ticket dispenser only gives2 tickets at a time then you can override the methods to allow this:

Issues in Testing Object Orientated Systems – James Gawn 11

Listing 3: A Different Improved Ticket Dispenser

pub l i c c l a s s NewTicketDispenser extendsTicketDispenser {

pub l i c boolean r e turnTicke t sAva i l ab l e ( ) {i f ( numberOfTicketsDispensed < ( numberOfTickets

− 1) ) {return true ;

} e l s e {return f a l s e ;

}}

pub l i c boolean pr in tT i cke t ( ) {i f ( r e tu rnTicke t sAva i l ab l e ( ) ) {

numberOfTicketsDispensed += 2 ;return true ;

} e l s e {return f a l s e ;

}}

}

There are a some of other more detailed aspects of inheritance that meritinterest these being composite and multiple inheritance and these are arediscussed in the next two sections.

2.4.2 Composite Inheritance

Composite inheritance is when there is some chaining of inheritance. Thiscan be when you have one class which is the super class, and its subclassis itself a superclass of another class. An good example of this is when youare using the Java programming language, in which every class which itselfdoes not inherit any classes always inherits from the object class. So inthe last example the TicketDispenser class implictly inherits from the object

Issues in Testing Object Orientated Systems – James Gawn 12

class even though it is not defined. So if this is taken in the context of ourNewTicketDispenser you get this kind of relationship:

This will have implications later when we start to deal with testing is-sues, but is an important principle that is often used when designing andimplementing systems in the object orientated paradigm.

2.4.3 Multiple Inheritance

In object orientated languages they can sometimes support what is called”multiple inheritance”, this is simply where a class is able to inherit methodsand variables from more than one superclass. The opposing case to this iswhen a language only allows a class to inherit from one class and one classalone, and this is most often called ”single inheritance”.

An example of multiple inheritance could be if you are modelling animals,you could end up with this kind of arrangement:

INSERT DIGRAM FROM P160 FROM Watt04

Issues in Testing Object Orientated Systems – James Gawn 13

Source: [2, P160]

As you can see in this diagram this can result in some interesting struc-tures, where you can see Eagle for instance, which is inheriting from twodifferent classes which both themselves inherit from the class Animal.

There are a number of complications that can affect a class that inheritsfrom more than one class, one of the most obvious of these is what happenswhen both classes that you inherit from have a method with the same name.This type of problem is often resolved in different ways depending on thelanguage used, but in Python for instance any ambigious methods/variablesare resolved by searching the various superclasses and finding the order inwhich they are declared [2, P424].

2.5 Polymorphism

In the object orientated paradigm polymorphism allows you to reference andcall methods on a set of objects not by their class, but by their superclass.To assist in explaining this further here is an example based on fruit:

Issues in Testing Object Orientated Systems – James Gawn 14

In this example you can see that there is a Fruit super class, that definesthat any Fruit object is able to be prepared in some generic way (such aswashing it). The sub class Orange then overrides the extended method pre-pare because it has to be pealed before you can eat it, where as Strawberrycan just use the extended generic fruit method.

So if in this example you wish to create some collection containing differ-ent types of fruit, and then you would like to iterate through each one andprepare them. Polymorphisim rather than requiring checking which type offruit it is before you call the prepare correct prepare method, you can justreference them as fruit, since they all have the fruit class as the super class.This is because you are guaranteed to have the prepare method due to themall inheriting from the fruit class.

Polymorphism generally takes two forms in a language, the first beingstatic polymorphism where the binding of these dynamic objects is made dur-ing compilation, with Ada95 being and example language using this method.This is apposed to dynamic polymorphism where the binding of the methodsis performed at run time instead, with Java being an example of this style ofpolymorphism. The first type of polymorphism has advantages because thebinding is occurring at compile time if there are any errors these are foundbefore the program is executed where in the second problems might not befound until run time which may cause faults.

Issues in Testing Object Orientated Systems – James Gawn 15

3 Testing Levels for Object Orientated Sys-

tems

3.1 Introducting Testing Levels

To enable a discussion about performing testing with object orientated sys-tems, you first have to have an understanding about the different levels oftesting that are required. This is the topic that this section will discuss.

The first distinction that we need to decide when dealing with objectorientated languages opposed to a traditional languages is how we definethe smallest unit to be tested at the lowest level. In a traditional testingenvironment a single function is normally the smallest unit that is tested,which is normally been programmed and often tested by one person. It isalso normally the smallest component of a system that is able to be compiledand executed on its own.

There are two options in selecting units for testing in an object orientatedlanguage, the first of these being an individual method within a class. Thesecond option for an unit is simply taking an entire class as a unit.

If we first look at taking a single method as a unit it can quickly be seenthat there are a number of issue that would have to be addressed. Firstlyyou can see that that it in itself might not be compilable, and even if it is,then it is possible that it might simply not run correctly. This could be thethe case if the method concerned uses variables which are stored within theinstantiated class and as such are not part of the method. Therefore if youwish to take a method as a unit you immediately are forced to break theconcept of the individual unit, because when when performing testing youwould need to have use variables external to the method.

There are of course benefits to testing at much lower levels, since it isknown that if you can find a error in a program earlier in the developmentyou can lower the costs to correct it[1, P350], but it similarly might be costlyto try testing at such a low level when there can be so many other factorsexternal to a method that can affect its operation.

Conversely if you take a class as a singular unit you can run into theproblem that the units may not be small any more. In following good styleguidelines classes should generally not be overly sized, but often this rulewill be broken when dealing with large and complex software. This can thencomplicate the testing process, due to no longer attempting to test a small

Issues in Testing Object Orientated Systems – James Gawn 16

simple section of code but rather a larger more complex one, where inherentlyit is harder to find errors.

This issue of selecting what constitutes a unit has results in two slightlydifferent approaches, where by you can either have three or four differentlevels of testing. So if you take methods as a unit you have four levels withthe ”method level” being the extra level, and with class units you simplychange the nature of the class level and don’t make use of the method level.

3.2 Method Level

In this level the individual methods are tested to ensure they on there own areworking as they are intended to by the specification. Although the intendedtesting is just for one method, it may be that other methods and variablesmay have to be included in the testing, to facilitate the testing of the methodcurrently under test. This might be the case for instance if you are testing amethod that calls one or more other methods within the same class, or indeedmakes use of any class wide variables. The methods that are included in thetesting could only be methods that have already been tested, otherwise thetests on the current method under test would not be valid. This is becauseif any of these methods are used as data sources by the method then if thedata provides is incorrect it could cause the test to show that the method isnot working correct despite the fact it may work perfectly with the correctdata.

This then brings up the need for so called stub methods/variables, theseare simply replacements for the real methods/variables which are often staticin nature and simply return values that are known to be true by the tester.This then negates any problems with the testing of a method which callsuntested methods, but of course then puts more of the burden on a detailedspecification and the accuracy of the stub methods created by the tester.

3.3 Class Level

In this level the class is tested as a whole, with each of the methods beingtested to ensure when a class is instantiated that the methods work correctlywith the given inputs. This level is also refered to when dealing with thefour level model as the intraclass testing level, where you ensure that whenyou interact with the different methods in the class the remaining methodsbehave in the correct way.

Issues in Testing Object Orientated Systems – James Gawn 17

Again similarly to the method level at class level it is very possible thatyou might have to include other classes during the testing of a class, simplybecause a class is dependant apon another class, for instance if it inheritsfeatures from another. This again can require the need for stub classes asmentioned in the method level (Section 3.2).

3.4 Integration Level

In this level the focus of the testing is in finding errors in classes that causefaults during communication between different classes, and to ensure thatthere is a minimum chance of these faults when you move onto the systemlevel of testing. This is an important level of testing, which is required toensure when classes are composed together with other classes that they workas intended.

This is significant phase of testing when you start to reuse classes in waysthat might not be initially expected. If the interface that has been createddoes not behave in the way in which is should, then when it comes to reusethe class in a later software package then the unexpected behaviour couldbe problematic. This is ever more an issue in particular when using objectorientated systems, one of the benefits of which is supposed to be easier reuse.It can also be considered that integration testing is in some way similar toclass testing, where class testing is the intraclass testing, and integrationtesting is interclass testing.

There are a number of different strategies for performing integration test-ing, a few of these include:

• Big Bang Integration - Immediately testing with all the classes together,which is rather a risky strategy and can make it difficult to find thecause of faults; but it can prove to provide quick results to whether asystem is working or not if there are time constraints.

• Bottom Up Integration - Testing the lowest classes in the hierarchicaltree and working up using drivers.

• Top Down Integration - Testing the highest classes in the hierarchicaltree and working down using stubs.

Issues in Testing Object Orientated Systems – James Gawn 18

3.5 System Level

At this final level the program is tested as a whole, and is mainly based onthe specification given for the application. This therefore results in systemlevel testing often mainly being based on functional testing techniques.

One of the main aims is to find errors that can only be found when dealingwith the application as a whole. Another aim of system testing is to ensurethat the application that has finally been developed does actually have allthe functionality required as per the specification from the view point of apotential end user, which essentially comes down to the question whether theapplication is finished and can be handed over to the end user.

It can be noted that due to the high level nature of system level testing it isgenerally the case that the testing schemes used for traditional languages canbe equally applied to those object orientated languages with good effect[1,P718]. In addition to this testing at this level is very dependent on anaccurate specification of the system that is meant to have been created,this can then be used as a basis to ensure that the feature set has beenimplemented correctly, and that there are no underling errors.

Issues in Testing Object Orientated Systems – James Gawn 19

4 Testing Object Orientated Systems

4.1 Overview

There are a variety of effects that using languages that make use of the objectorientated paradigm have in regards to testing, ranging from complicationswith encapsulation to the results of using inheritance and polymorphism. Inthis section some of these issues will be discussed.

4.2 Encapsulation

Encapsulation as stated earlier provides classes a way to control access toits methods and variables. This ability itself does not create a significantamount of bugs apart from attempting to access components that have beenset to private or protected.

The main issue with encapsulation is that it can make structural testingof a class more complicated to carry out. In order to perform accurate testingyou need to be able to query the state of an object at every stage of execution,and to achieve this you would require access to all of the object variables.This can be an issue because as we have seen if variables have been set toprivate or protected that is entirely possible that you might not have accessto be able to retrieve the variables in order to be able to see the state.

The obvious solution to this is to then simply make all of the fields public,but the issue here is that although you can then directly query the state ofan object at all times you have intrinsically changed the system under test.By changing the source code of the object to perform testing it is likely thatsome problems might not be found in the finally program that has the correctencapsulation applied. The most obvious of these is one of the methods thatare being tested accesses a private variable that has been set to public forthe purpose of the test.

Another option could well be to use a series of accessor methods, butagain here you are changing the code which is contained within the unitunder test. So if when you come to remove these accessor methods youaccidentally remove an accessor method that is supposed to exist you mayhave created an error that would not have originally existed.

Now if you consider the example ticket machine that has been discussedpreviously (See listing 1), and you now have a new class that monitors thenumber of tickets available by directly accessing the ”numberOfTickets” and

Issues in Testing Object Orientated Systems – James Gawn 20

”numberOfTicketsDispensed” variables. If you remember both of these vari-ables have been set to private/protected which means under normal condi-tions when trying to access them directly an error would be returned. If wenow proceed with testing by making all the variables public in order to querythe state of the object during testing, this system appears to be working. Ofcourse in reality when the variables are made private again for the final com-pletion of the program it will not work, this of course is an obstacle thatneeds to be overcome.

4.3 Inheritance

Earlier in chapter 2.4 the basic principles of inheritance for object orientatedlanguages were discussed, further to this this chapter this one will continueto discuss some of the testing issues which are related to this aspect of objectorientated languages.

One complication with the concept of inheritance is the trouble in un-derstanding the actual feature set a class provides in a large system. It isentirely possible for you to have a class with only one method in it, but if itinherits from one or more classes, which themselves inherit a large numberof features. This can make it hard to distinguish the precise methods andvariables that the class you are testing is supposed to have, in particularwhen you allow multiple inheritance. This can be all the more difficult whenyou start taking into account overiding of methods, which can then obfus-cate what a method actual does. You can of course use the specification todefine what the class is supposed to have as it features, but this in itself onlyhelps with functional testing, rather than facilitating the equally importantstructural testing.

An important issue that needs to be addressed when considering testinga class which extends from another is what testing is required for the variousmethods that are inherited/overridden. Here are a few key issues that needto be addressed:

• Do you need to retest the inherited methods, and if you do can youreuse the tests from the superclass?

• Can tests created for the superclass be reused to test methods in thesuperclass that have been overridden?

Issues in Testing Object Orientated Systems – James Gawn 21

If you first consider the class which is being extended has already beenexhaustively tested, and is known to work as intended. The issue of needingto retest the inherited methods is straightforward, and the answer is yes youdo need to test them again. This is because although the actual code beingexecuted is the same, there could be changes to methods which the methodunder test calls within the class that might change the expected behaviour.These changes then require for the tests to be run again, to ensure that it willwork as intended. Although the elements of reuse are somewhat damagedin this inheritance system there is some light at the end of the tunnel, thatbeing you are to use the tests designed for the superclass at least as a basisto test the method in the subclass.

Due to the method being overridden it is likely to be a specialisationof the superclasses method and this will mean that potentially some of theinput conditions could have been changed although the type of the inputsand outputs will remain the same. This means that a limited amount of thetests created for the superclass may be relevent but more than likely a newset of tests will be required.

One last thought is that the reusablility of the test cases is reliant on thecorrect use of inheritance. By this it is meant that inheritance is used in away to represent or model a relationship, for example a class Media, withsubclasses DVD and Video. In the example you can see that a Media classin some way represents both DVD’s and Videos and shares properties. Inthis case reusablity of test cases is easier, but conversely if you simply userinheritance because it is easier than structuring the program in the correctmanner then it will become more difficult if at all possible to resuse the testcases[1, P500].

However there are some benefits if you do focus on a specification basedtesting (functional testing) when you come to testing a subclass, you may beable to reuse a test suites [1, P75] reducing some of the effort in testing thesub class as you may only need to create test suits for the new methods.

A number of testing axioms exists that clarify some of the issues sur-rounding inheritances effect on testing which are antiextensionality, antide-composition, and anticomposition[1, P505].

Antiextensionality means that if you have a test suite for a method in asubclass which provides good coverage it does not necessarly provide equallygood coverage in another subclass. Therefore this means that if you havea set of subclasses that in order to perform high quality testing on each ofthem you will need to create modified test cases for each.

Issues in Testing Object Orientated Systems – James Gawn 22

The antidecomposition axiom means that if good test coverage is achievedon one class in a system that does not necessarily mean that any classesthat the tested class calls have been equally well covered. Therefore if youthen wish to provide good levels of testing coverage you then need to createseparate test suits for each class individually.

Finally the last axiom anticomposition simply means that if you havegood coverage on each individual method within a class, this itself does notmean that you have tested well the class as a whole. Implicitly from thisyou can infer that you need to create test suits that cover not just individualmethods but rather the class as a whole also, and of course this is reflectedby the testing levels, namely Method testing, and Class testing.

4.3.1 Class Flattening

One solution to make testing of systems with inheritance easier is to performwhat is called class flattening. This simply put flattens the class heriachythat you would normal see in a class diagram:

As can be seen in the ticket machine example that we have above if wewere at this point to flatten the NewTicketDispenser class in order to performtesting it would result in all the methods and variables that are protected orpublic being transfered into the NewTicketDispenser class:

Issues in Testing Object Orientated Systems – James Gawn 23

Listing 4: A Flattened NewTicketDispenser

pub l i c c l a s s NewTicketDispenser {

pr i va t e i n t numberOfTickets ;p r i va t e i n t numberOfTicketsDispensed ;

pub l i c NewTicketDispenser ( i n t numberOfTickets ) {t h i s . numberOfTickets = numberOfTickets ;

numberOfTicketsDispensed = 0 ;}pub l i c boolean r e turnTicke t sAva i l ab l e ( ) {

i f ( numberOfTicketsDispensed <

numberOfTickets ) {return true ;

} e l s e {return f a l s e ;

}}pub l i c boolean pr in tT i cke t ( ) {

i f ( r e tu rnTicke t sAva i l ab l e ( ) ) {numberOfTicketsDispensed++;return true ;

} e l s e {return f a l s e ;

}}pub l i c i n t returnNoOfTicket sAva i lab le ( ) {

return numberOfTickets −numberOfTicketsDispensed ;

}}

Firstly it should be noted that in this demonstration of class flatteningthat the Java Object class has been left out simply for ease of demonstration,but it is unnecessary for this simple example.

Issues in Testing Object Orientated Systems – James Gawn 24

This process then results in an explicit class which can then more easilybe tested, due to all its features being present in the class rather that beingspread throughout the class hierarchy. It forces the tester to then considerduring the flatting process any ambiguities as a result of multiple inheritance,providing that there is an understanding of the way in which the targetprogramming language handles these.

4.4 Polymorphism

One of the first issues that you have to consider when dealing with testinga system making use of polymorphism is that it creates complex relation-ships between classes that must be properly be understood before you havea chance to create test suites that can test a system effectively.

A safe approach has been devised that gives testers a clear and concise wayto perform a good level of testing on polymorphic classes[1, P659] when deal-ing with what could be potentially a huge number of tests required withoutsome kind of culling. This approach requires that every class in the systemunder test has at least these three testing goals achieved during integrationtesting:

1. Each method in class must have complete branch coverage, thereforefor each branch both possible the true and false options are taken.

2. If the class is polymorphic in nature then every method that may bebound dynamically must be tested at least once.

3. All methods called by the class under test on other polymorphic objectsmust be tested at least once, and each possible binding for polymorphicobject must be tried.

If all these above points have been met then you would be able to saythat the classes in question have been tested effectivly.

Issues in Testing Object Orientated Systems – James Gawn 25

5 Summary

5.1 Conclusions

In conclusion there are a range of different testing related issues that need tobe considered before embarking on testing a system that has been created.The simple suggestion that because you are using an object orientated lan-guage it does not automatically mean that once you have tested a class once,that when you come to reuse it that it will not need to be tested. It is infact rather more complicated than that, although through object orientatedlanguages you can make it conceptually easier to reuse code, which in turncan reduce the number of errors[1, P69] careful testing strategies still needto be created.

5.2 Futher Work

There is a large variety of follow up work that can continue on from thisdocument. One of the clearest steps onwards is to look further at the practi-calities of testing at each of the different testing levels, as well as looking atthe implementations of the object orinetation paradigm and how this effectsthe testing process in each case. Another angle that could be taken is lookingat various automation efforts for each of these levels, in particular at how byusing UML test case generation can be automated in some cases.

One possible avenue for further study could be to continue with simplylooking in more detail at the benefits and pitfalls of the different types ofintegration testing (for example big band or top down), or looking at how itcan be easier with the help of UML to build test suits at the system level.

Again an even deeper level you could try some practical examples oftesting a system and actually try the different methods to see how practicalthey actually are, moving slightly away from the theoretics of testing.

Issues in Testing Object Orientated Systems – James Gawn 26

References

[1] Robert V. Binder, Testing Object Orientated Systems, 6thPrinting, Addison-Wesley, 2005

[2] David Watt, Programming Languages and Design Concepts,Wiley, 2004

[3] Ian Sommerville, Software Engineering, Eighth Edition, Addi-son Wesley, 2007

[4] Paul C. Jorgensen, Software Testing: A Craftsman’s Approach,Second Edition, CRC Press, 2005