12.4 design test cases
Currently, the design of test cases for Object-Oriented software is still in the research and development stage. Unlike traditional software testing (the design of test cases is driven by the input processing output view of the software or the algorithm details of a single module, object-oriented testing focuses on designing appropriate operation sequences to check the status of classes.
12.4.1 methods of the test class
As mentioned above, software testing has gradually transitioned from "small test" to "Large test ". For object-oriented software, small tests focus on testing the encapsulated methods in a single class and class. Methods for testing a single class include random testing, Division testing, and fault-based testing.
1. random test
The following uses an example of a banking application system to briefly describe this test method. The account class of the system has the following operations: open, setup, deposit (deposit), withdraw (withdrawal), balance (balance ), summarize, creditlimit, and close ). Each operation in the above column can be applied to an account instance. However, the nature of the system also imposes some restrictions on the application of the operation. For example, you must open an account before applying other operations, the account can be closed only after all operations are completed. Even with these restrictions, there are many ways to arrange operations. The minimum behavior history of an account instance includes the following operations:
Open · setup · deposit · withdraw · close
This is the minimum test sequence for the Account class. However, many other behaviors may occur in the following sequence:
Open · setup · deposit · [Deposit | withdraw | balance | summarize | creditlimit] n · withdraw · close
The sequence of the upper column can generate a series of different operation sequences randomly, for example:
Test Case # r1: Open · setup · deposit · Balance · summarize · withdraw · close
Test Case # R2: Open · setup · deposit · withdraw · deposit · Balance · creditlimit ·
Withdraw · close
Execute these and other randomly generated test cases to test the different survival history of the class instance.
2. Division Test
Similar to the equivalent division method used for testing traditional software, the partition test method can reduce the number of test cases required for testing classes. First, classify input and output, and then design test cases to test each category. The following describes the classification method.
(1) status-based division
This method is used to classify operations based on the ability of class operations to change the class status. Next, consider the account class. Status operations include deposit and withdraw, while non-State operations include balance, summarize, and creditlimit. Design test cases to test the operations that change the status and those that do not change the status respectively. For example, you can use this method to design the following test cases:
Test Case # P1: Open · setup · deposit · withdraw · close
Test Case # P2: Open · setup · deposit · summarize · creditlimit · withdraw · close
Test Case # P1 changes the State, while Test Case # P2 does not change the state (except for operations in the minimum test sequence ).
(2) attribute-based division
This method classifies operations based on the attributes used by class operations. For the account class, you can use the property balance to define the division and divide the operation into three categories:
. Use balance operations;
. Modify the balance operation;
. Do not use or modify the balance operation.
Then, design a test sequence for each category.
(3) function-based division
This method classifies operations based on the functions completed by class operations. For example, you can classify operations in the account class into initialization operations (open, setup), computing operations (deposit, withdraw), query operations (balance, summarize, creditlimit) and terminate the operation (close ). Then design a test sequence for each category.
3. fault-based testing
The fault-based test is similar to the traditional error inference method. It is also the first to speculate the possible errors in the software, and then design the test cases most likely to discover these errors. For example, software engineers often make mistakes at the problem boundary. Therefore, when testing the SQRT (calculate the square root) operation (this operation returns an error message when the input is negative, check the boundary: a negative number close to zero and zero itself. "Zero" is used to check whether the programmer has made the following mistake:
Set the statement if (x> = 0) calculate_square_root ();
If (x> 0) calculate_square_root ();
In order to predict possible errors in the software, the analysis model and design model should be carefully studied, and the experience and intuition of testers should be largely relied on. If the prediction is accurate, a fault-based test method can be used to detect a large number of errors with a relatively low workload. Otherwise, if the prediction is inaccurate, the effect of this method is not better than that of the random test technology.
12.4.2 integration test method
After the integration of object-oriented systems, the design of test cases becomes more complex. In this test phase, inter-class collaboration must be tested. To illustrate how to design inter-class test cases, expand the example of the banking system introduced in section 12.4.1 so that it contains the classes and collaboration shown in Figure 12.3. In the figure, the arrow direction represents the message transmission direction. The labeling on the arrow line shows the operations called as the result of the message's collaboration.
Similar to a single test class, test class collaboration can be completed using random test methods, partitioning test methods, and scenario-based and Behavior tests.
1. Multi-Class Tests
We recommend that you use the following steps to generate random test cases for multiple classes.
For each customer class, use the class operator list to generate a series of random test sequences. These operators send messages to server-class instances
For each generated message, determine the cooperation class and Corresponding operators in the server object.
For each operator in the Server Object (which has been called by a message from the customer object), determine the transmitted message.
For each message, determine the operators called at the next layer, and combine these operators into the test sequence.
To illustrate how to use the preceding steps to generate random test cases for multiple classes, consider the sequence of operations between the bank class and the ATM class (see Figure 12.3:
Verifyacct · verifypin · [(verifypolicy · withdrawreq) | depositreq | acctinforeq] n
The random test cases for the bank class may be:
Test Case # R3: verifyacct · verifypin · depositreq
To consider the collaborators involved in this test, you need to consider the messages associated with each operation in test case # R3. The bank must work with validationinfo to execute verifyacct and verifypin, and the bank must also work with the account to execute depositreq. Therefore, the new test cases for testing the collaboration mentioned above are:
Test Case # R4: verifyacctbank · [validacctvalidationinfo] · verifypinbank · [validpinvalidationinfo] · depositreq · [depositaccount]
The test method for dividing multiple classes is similar to the test method for dividing a single class (see section 12.4.1 ). However, for multiple types of tests, the test sequence should be expanded to include the operations called by messages sent to the collaboration class. Another classification test method is to classify operations based on interfaces of specific classes. As shown in Figure 12.3, the Bank class receives messages from the ATM class and the cashier class. Therefore, you can test the methods in the bank class by dividing them into ATM and cashier. You can also use status-based Division (see section 12.4.1) to further refine the division.
Figure 12.3 banking system class-collaboration Diagram
2. Export test cases from Dynamic Models
In Chapter 9th, we have already discussed how to use a state transition diagram as a model to represent the dynamic behavior of a class. The class status chart helps us export test cases for testing the dynamic behavior of the class (and those classes that work with it. Figure 12.4 shows the status chart of the account class discussed earlier. As shown in the figure, the initial conversion has passed the empty Acct and setup Acct statuses, most of the behavior of a class instance occurs in the working Acct status. The final withdraw and close make the account class switch to the nonworking Acct status and dead Acct status respectively.
Figure 12.4 status transition of the account class
The designed test case should cover all States, that is, the Operation Sequence should make the account-class instance traverse all permitted state transitions:
Test Case # S1: Open · setupaccnt · deposit (initial) · withdraw (final) · close
Note that the sequence listed above is the same as the minimum test sequence discussed in section 12.4.1. Add an additional test sequence to the minimum sequence to obtain other test cases:
Test Case # S2: Open · setupaccnt · deposit (initial) · deposit · Balance · credit · withdraw (final) · close
Test Case # S3: Open · setupaccnt · deposit (initial) · deposit · withdraw · accntinfo · withdraw (final) · close
You can also export more test cases to ensure that all behaviors of the class are tested properly. When one or more classes are collaboratively formed by class behavior, multiple status diagrams should be used to track the behavior flow of the system.