250 likes | 364 Views
Testing Things That Seem Hard To Test. Robert Koss, Ph. D. ObjectMentor, Inc. koss@objectmentor.com www.objectmentor.com. Introduction. XP dictates that we test everything that can possibly break Subjective accessors and mutators What if mutator does validation?
E N D
Testing Things That Seem Hard To Test Robert Koss, Ph. D.ObjectMentor, Inc. koss@objectmentor.com www.objectmentor.com (c) 2002 Object Mentor, Inc.
Introduction • XP dictates that we test everything that can possibly break • Subjective • accessors and mutators • What if mutator does validation? • How much logic is too much? • What if class Foo is difficult to test? FooTest Foo (c) 2002 Object Mentor, Inc.
Sources of Difficulty • Some objects appear to be difficult to test • Objects which depend upon other objects. • GUI’s • Databases • Servlets / EJB’s • What makes these things hard to test? • Not knowing what to test • Source code dependencies • Collaborating objects (c) 2002 Object Mentor, Inc.
Knowing What to Test • GUI • Assume Swing / MFC works • Model-View-Controller • Make sure anything that can break is in a class which can be tested • Databases • Assume Oracle / SQL Server, etc. works • Servlets • HttpUnit • Delegate to a class which can be tested. (c) 2002 Object Mentor, Inc.
Collaborating Objects • Mark IV Coffee Maker public void testMakeCoffee() { CoffeeMaker cm = new CoffeeMaker(); cm.makeCoffee(); assert( ? ? ? ); } (c) 2002 Object Mentor, Inc.
Breaking Troublesome Dependencies • A source-code dependency can always be broken by the judicious use of an interface. • Dependency has been inverted • Both A and B now depend upon an interface • A no longer knows concrete type of B • Can now test A by supplying a MockB (c) 2002 Object Mentor, Inc.
Mock Objects / Stubs • Class A can’t tell if message goes to class B or class BStub • Class BStub used to create testing environment, totally under control of class ATest (c) 2002 Object Mentor, Inc.
Self-Shunt Pattern • Not always necessary to make a new class and create a new object for Bstub • Class ATest can implement the IB interface (c) 2002 Object Mentor, Inc.
CoffeeMakerTest • Stub out Warmer and Boiler (c) 2002 Object Mentor, Inc.
Stubs Everywhere ? • Stubs are good when real class can’t easily be used • Hardware • Database • Dependent class not done • Not necessary for Value Objects • Not necessary if dependants are known to work (c) 2002 Object Mentor, Inc.
Chains of Dependencies • Bowling Game • Boom, Splash, (x, y, z, t) (c) 2002 Object Mentor, Inc.
More Uses for Stubs • Logging • When object under test is supposed to send a sequence of messages to another object in a specific order • Record message sent as a string • append to string for each message • Alternative to setting several flags and examining in test (c) 2002 Object Mentor, Inc.
More Uses for Stubs • Null Object Pattern • When doing nothing is the right thing to do • Don’t have to test for presence of Logger object (c) 2002 Object Mentor, Inc.
Testing GUI’s • Test Model (MVC) first • Concentrate on business instead of user interface • Start just inside the UI • Quicken • addCheck( new Check( checkNum, payee, amount)) is more important than a fancy check gui • Same with reconcile() (c) 2002 Object Mentor, Inc.
Testing GUI’s • Decide what to test • Can test everything except for aestetics • Should we? • http://users.vnet.net/wwake/xp/xp0001/ public void testWidgetsPresent() { SearchPanel panel = new SearchPanel(); assertNotNull(panel.searchLabel); assertNotNull(panel.queryField); assertNotNull(panel.findButton); assertNotNull(panel.resultTable); } (c) 2002 Object Mentor, Inc.
Being Pragmatic • Assume GUI toolkit works • Swing, MFC, Qt, GTK • new Button( “OK”); • Continually ask if code being written can possibly break • Continually ask if code being written is doing more than UI • Make sure all logic is in classes that can be tested • Make GUI code so thin that it can’t possibly break. (c) 2002 Object Mentor, Inc.
Separate Domain From User Interface • Model - View - Controller • Document - View • Combines traditional View with Controller • Good unless several Controllers are needed • Model - View - Presenter • http://www-106.ibm.com/developerworks/library/mvp.html • Combines traditional View with Controller • Adds another layer between UI and Model • Presenter is ideal place to do unit testing of GUI (c) 2002 Object Mentor, Inc.
Single Responsibility Principle • A class has a single responsibility. It meets that responsibility, the whole responsibility, and nothing but that responsibility • Called cohesion in Structured Design • Applied to functions • Rule of thumb • Describe class’s responsibility without using “and” • What is the responsibility of an event handler? • “Handles” event • Scope of “handle” subjective • Should not have any program logic (c) 2002 Object Mentor, Inc.
A Stupid GUI Is an Unbreakable GUI • Event handler should do nothing but gather the information from event and delegate responsibility to another class • Can’t possibly break • e.g., MouseEventHandler should get click coordinates and delegate to another class that knows what to do when the mouse is clicked • hit testing (c) 2002 Object Mentor, Inc.
Event Handlers • Dialog / Window with GUI Control and registered listener • Testing listener can be • Easy / Annoying • Hard / Impossible How do we test this? (c) 2002 Object Mentor, Inc.
Event Handlers Delegate • Have event handler delegate to something that can be tested Presenter (MVP) (c) 2002 Object Mentor, Inc.
General Architecture • Note the direction of the dependencies Make this unbreakable (c) 2002 Object Mentor, Inc.
Interacting GUI Components • Interaction with one GUI component causes changes to other components. • Menus becoming active / inactive • Toolbar changes • Mediator Pattern • Have each event handler delegate to mediator and have mediator determine what else must change • Component interactions now localized (and testable!) instead of being distributed over all event handlers. (c) 2002 Object Mentor, Inc.
Mediators as State Machines • Using a Mediator localizes inter-object communication • Mediators can become ugly for complicated windows • Implementing Mediator as a state machine makes it easy to get the wiring correct and to easily accommodate changes (c) 2002 Object Mentor, Inc.
Summary • We have to test everything that can possibly break • If something appears hard to test, don’t let it do anything that can break • Delegate to an object that can be tested (c) 2002 Object Mentor, Inc.