Many researchers [11, 44, 85, 116, 130, 200] have proposed different approaches to compute slices of Java programs. Some of the slicing mechanisms are based on the dependence graphs like PDG and SDG, while other approaches are based on the Java byte-code analysis. To overcome the limitations and increase the efficiency of O-O slicing techniques, Kovacs et al. [116] proposed a static inter-procedural slicing of Java programs. This approach focuses on representing special Java features for improving the efficiency of the slicing technique. The proposed slicing approach can handle static variables, multiple packages, and interfaces. They also enhanced the SDG of the program by incorporating the polymorphic calls without requiring extra nodes for the purpose.
Chen et al. [44] proposed a new approach for graphically representing the O- O Java software. The authors discussed different dependences possible in a Java program and proposed slicing of classes based on program dependence graph (PDG). In their method, the program dependence graph consists of a set of independent PDGs. In slicing of classes, the slicing criterion taken is hs, v, classi, where s is the statement number, v is the variable and class is the name of the class to be sliced. The slice is computed by traversing backward from s and marking all the statements and data members used in the class based on the PDG. Based on this new model of program representation Chen et al. [44] also introduced the concepts of partial slicing, object slicing, and class slicing.
Allen et al. [11] extended the work of Chen et al. [44] on program slicing by using SDG. In their work, they proposed slicing of programs in the presence of exceptions. The focus was mainly to determine the control and data dependences due to the presence of try, catch and throw blocks in the program. They have not considered other Java specific features (such as interface, super, polymorphic calls, and template classes) for slicing. But, in our approach, we have considered the O-O features like packages, super, method overriding, etc. for the purpose of slicing.
Wang et al. [200] proposed a technique for slicing of Java programs by using compressed byte-code traces. They represented the byte-code corresponding to an execution trace of a Java program. Then, through backward traversal of the execution trace, they determined the control and data dependences on the slicing criterion. This approach requires the trace table to be constructed for each method. If a program will have too many methods, then this approach will be disadvanta- geous to compute the slices. This is because of the increased execution overhead in maintaining the execution trace tables. This work is also silent regarding the
execution trace of the methods that are nested, overloaded and/or overridden.
Similarly, Hammer et al. [85] proposed a method for slicing of Java programs in the presence of objects as parameters. The analysis of the dependences is based upon an Intermediate Representation (IR) generated from the byte-code of the program. A good point-to analysis is a prerequisite of this algorithm to compute more precise slices.
Li et al. [130] proposed a hierarchical slicing technique to slice Java programs. The slicing algorithm is implemented on a tool, named JATO. Hierarchical slicing is computed level wise, starting from the package level to statement level. Li et al. [130] simplified the program representation by introducing a level-wise graphical rep- resentation of object-oriented programs at different levels of program organization such as package level, class level, method level and statement level. Four differ- ent graphs are constructed one at each level, these are Package Level Dependence
Graph (PLDG), Class Level Dependence Graph (CLDG), Method Level Dependence Graph (MLDG), System Level Dependence Graph (SLDG). This hierarchical slicing
approach requires four different slicing criteria to be set, one at each hierarchical level. However, the traversal of the graph from package level to statement level resulted in imprecise slices.
Slicing of Java programs in all of the above work [11, 44, 85, 116, 200] was pro- posed by taking into consideration a specific feature or type of dependence present in a Java program. Whereas, the overall impact of the features on the dependences such as the dependence due to the presence of packages and other specific Java fea- tures are not considered. Our approach has made a decent effort in analyzing all the possible dependences in O-O programs and computing a more accurate slice. To be able to employ slicing for regression testing, we need to identify all those statements that affect the modified statement and those statements that may get affected by the modification. But, most of the existing approaches [11, 44, 85, 200] are based upon either forward traversing or backward traversing. This will only result in the partial identification of the affected statements due to the modification. But, our approach is better suited for regression testing due to the following reason: both forward and backward traversals of our approach are suitable for an efficient change impact analysis, as they correctly find those program parts that may be affected or may affect other program parts due to the change.
3.2
Regression Testing
An informal meaning to the word regress is to return back to an existing previous state. Regression testing is the process to ensure that a program has not regressed back to the faulty state after the changes are made to it. Regression testing can be either progressive or corrective according to Leung and White [127]. Progres- sive regression testing involves retesting of the major changes that are made to the specification of a program. Whereas corrective regression testing performs retesting only on minor modifications that do not affect the overall program structure. To ensure that the functionality in the new version of the program works correctly after its modification, Gupta et al. [81] proposed a program slicing based regres- sion testing technique. This approach relies on solving the data flow equations to explicitly detect def-use associations that are affected by a program change. The algorithm first makes a backward traversal and then makes a forward traversal from the point of change to find the affected def-use associations. This slicing technique relies neither on the data flow history nor on re-computation of data flow for the entire program to detect the affected definition-use associations. The changes made to the program initiate the necessary partial data flow re-computation through slic- ing. This approach achieves the same testing coverage as achieved by retesting with all the test cases without maintaining a test suite. Thus, it eliminates the overhead of maintaining a test suite.
Leung and White [127] classified the initial test cases into different categories such as reusable, retestable, obsolete, and adding new-structural and new-specification test cases. Then they suggested to select the test cases from any one of the test cases or from all the categories. Harrold and Sofa [94] have provided a strategy for unit and integration regression testing by combining the data flow testing with the incremental data flow analysis. Harrold et al. [91] gave a methodology to select a minimal number of test cases that ensure the correctness of all the requirements of a module. A safe algorithm based on the dependence graph of a module is given by Rothermel et al. [173]. This approach selects those test cases for regression testing that results in a different output than the original output. Binkley [23] gave a semantic differencing based approach to reduce the cost of regression test- ing. An integer programming problem formulation was proposed by Fischer [71], which was extended in [95] and solved by using natural optimization in [145] for optimal retesting. Some researchers [145, 146] have used evolutionary algorithms like genetic algorithms to solve the problem of regression testing. Some software
tools for regression testing based on the above mentioned approaches are available in [43, 205, 206]. According to Rothermel et al. [176], complete regression testing of a software of 20,000 lines of code require around seven weeks of continuous execu- tion. This necessitates development of many techniques to enhance the efficiency of regression testing (selection, minimization, and prioritization). Some existing work on these regression testing techniques are discussed in the next subsequent sections.