290 likes | 415 Views
This lecture discusses the complexities of testing object-oriented (OO) software, emphasizing complete test coverage of a class by testing all operations, attributes, and states. It explores scenario-based testing, focusing on functional requirements derived from use cases and UML diagrams. The lecture outlines practical test procedures, including establishing testing budgets, developing test case matrices, and defining conditions for successful execution. Through examples like ATM session establishment, it highlights the importance of ensuring comprehensive test case documentation to identify gaps and verify system behavior against expected outputs.
E N D
CS451Lecture 9: OO Testing Yugi Lee STB #555 (816) 235-5932 leeyu@umkc.edu www.sice.umkc.edu/~leeyu
Object class testing • Complete test coverage of a class involves • Testing all operations associated with an object • Setting and interrogating all object attributes • Exercising the object in all possible states • Inheritance makes it more difficult to design object class tests as the information to be tested is not localised
Testing OO software • Based on UML specifications • Use cases • Class diagrams • State transition diagrams • … • Problem: Effort focus on requirements not comprehensive quality?
Scenario based testing • Concentrates on (functional) requirements • Based on • use cases • corresponding sequence diagrams • Tests normal as well as exceptional behavior
Test Procedure (1) • Establish testing budget • Rank Use Cases (& variants) according to • Relative frequencies • Criticality • Allocate #test cases to each use case (and possibly variants) • Develop test cases for scenarios
Testing a use case/scenarios (1) • A scenario is a path through a sequence diagram • There are many different scenarios associated with a sequence diagram!
What can be wrong? • Incorrect or missing output • Missing function/feature in an object • Incorrect parameter values boundary value analysis • Correct message - wrong object • Incorrect message - right object • Incorrect object state • Message sent to destroyed object • Incorrect exception thrown • Incorrect exception handling • Incorrect assumption about receiver’s class • Class casts
Testing a use case/scenarios (2) • All paths in sequence diagram should be executed • Focus on messages from the actor/UI to the system • If possible: check “internal” objects • Extract control flow information from a sequence diagram • Test branches and loops • Test exceptions • Consider state
Example (cont.) • Several checks are performed • Is the card an ATM card? • Is the card stolen? • Has the customer a valid bank account? • Has the customer a valid PIN? • Three chances to enter the PIN • Service charge if from different bank
Test Procedure (2) • Translate the sequence diagram into a flow graph • Each message or group of consecutive messages becomes a segment (box). • A conditional action (branch, iteration) ends a segment • Each bracketed (loop) condition becomes a decision (hexagon)
Path conditions • Input and object state need to satisfy the path conditions • Identify predicates on each path, work from first predicate and identify required input and state variable values • Do the same for the next path conditions until the last one • Some paths may not be feasible
Special cases • Sequence diagrams rarely include two significant details: • Polymorphism: receiver has to be of a specific type but not an instance of one specific class • If needed: check instances of different classes • Exception-handling: “jumping out” of the sequence diagram • Catch exception
Test Procedure (3) • Develop the Use Case / Class coverage matrix • Analyze matrix • Which classes are not covered by test cases? • Which methods of a class are not covered? • Create additional test cases
Test case document • Usual cover information • Use case test descriptions • References • Appendices
Test Procedure (4) • Define test case • Name • Unique number • Textual description of test procedure • Based on flow graph and conditions • Includes expected results after each step define condition that allows to determine if the step succeeded or failed
Use case test descriptions • For every use case/sequence diagram in the design document • a test case that shows that the scenarios and its variations can be executed by the system • describe as precondition the objects and their state that get messages from the UI • As steps: list the sequence of messages that are send from the UI to other objects • test cases for all exceptions of the use case
Example: Test case definition (1) Test “Establish session” UID: 0001 Description: Precondition: ATM is running and no sessions exist … Step 1: test “begin session” To execute: Create a session object Expected result: session object exists and is in its initial state Step 2: test “no ATM card was entered” Precondition: Card entered is no ATM card To execute: Read card Expected result: NoATMCard exception is thrown and session object was deleted
Example: Test case definition (2) … Step 3: test “get PIN” Precondition: Card entered is ATM card To execute (a): displayEnterPIN Expected result: “Enter PIN” is displayed To execute (b): getEntry Expected result: 4 digit entry of a stolen card To execute (c): checkCard Expected result: StolenCardException is thrown …
Example: Test case definition (3) … To execute (d): getEntry Expected result: 4 digit entry of invalid account To execute (e): checkCard Expected result: false To execute (g): getEntry Expected result: 4 digit entry of valid account To execute (h): checkCard Expected result: true …
Executing tests • Develop automatic test drivers • In assignment: test driver should run on CLIENT side to make sure that the client/server communication is properly implemented • Use case tests • develop test classes that execute the use cases without user involvement • Test the use cases manually with UI • System test driver calls all use case test classes
Implementing test cases • Test driver code must • create the system state described in the test case • call the method to test • check if the expected result is produced • print test result to file/console e.g. • count the number of failed test to produce a summary result at the end
Test driver (1) package atm.impl.test; public class ATMUseCaseTest { private int allErrors = 0; //count #errors private void usecase1 () { //test use case 1 try{ System.out.println(“========“); System.out.println(“Testing Use Case 1: Establish Session”); testStep1(); testStep2(); testStep3(); … System.out.print(“Establish Session: Errors found = ”, allErrors); System.out.print(“Finished testing Use Case 1: Establish Session”); } catch (Exception anExc) {System.out.println(“Unexpected exception “, anExc, “in Use Case 1”); allErrors = allErrors +1; System.out.print(“Establish Session: Errors found = ”, allErrors); System.out.println(“Testing Use Case 1: Establish Session”);} } …
Test driver (2) private void testStep1() { try{//test step 1 of use case 1 System.out.print(“Testing Step 1: Begin Session ”); //create precondition/state //execute test Session aSession = new Session(); //check postcondition and print result if (aSession == null) {System.out.println(“failed”); allErrors = allErrors + 1; } else {System.out.println(“succeeded”);} } catch (Exception anExc) {System.out.println(“Unexpected exception “, anExc, “in Step 1”); allErrors = allErrors + 1; } } …