Generating Unit Tests for Checking Refactoring Safety Gustavo Soares, Rohit Gheyi, Tiago Massoni Márcio Cornélio, Diego Cavalcanti UFCG / UPE {gsoares, rohit, massoni, diegot}@dsc.ufcg.edu.br marcio@dsc.upe.br 1
Context Refactoring must preserve the external behavior of the code It can be manual, which is error-prone and time consuming Example: Rename Class Name Conflicts Where is it used? 2
Refactoring Tools In order to help the refactoring process, several tools automate a number of refactorings Eclipse Netbeans JBuilder IntelliJ 3
Motivating Example Incorrect Handling of Type Accesses Source A int k() B int k() Push Down refactoring Target A int k() B int k() Where int m() { return super.k(); } int m() Tools C C int test() int m() int test() 4
Problem Refactoring tools may perform erroneous transformations, changing the behavior of the code 5
Refactoring Conditions Source Target R I R Refactoring R Refactoring Conditions I Implemented Conditions 6
Behavioral Change Errors Developers rely on tests to attest that behavior is preserved Many times, it goes undetected Situations The software may not has a test suite The test suite is often refactored as well, which may lead to bugs 7
Goal A technique to increase the chances to identify refactoring errors. We focus on behavioral change errors. 8
Technique Static Analysis Methods Source program 1 5? Target program 3 Test Suite 4 2 Unit Test Generator Refactoring Change 9
Example Push Down method Source 1 Target A int A.k() int B.k() int C.test() A int k() int k() B int k() int m() C int test() 2 Randoop 3 4 500 tests 500/500 400/500 5 The transformation is not safe! B int k() C int test() int m() 10
Evaluation The technique was evaluated against 16 wrong transformations intended to be refactorings All transformations were applied by the best Java refactoring tools and that do not preserve the behavior of the code Eclipse Netbeans JBuilder IntelliJ 11
Transformations Characteristics Small programs Up to 4 classes Inheritance and Inner classes Up to 4 methods override and overload 12
Evaluated Refactorings Refactoring Rename (class, variable, method) Encapsulate field Extract (method, class) Push Down method Pull up method 3 out of 5 of those refactorings are in top 4 of most used refactorings for Java developers on Eclipse 13
Evaluation Results Our technique detected problems in all 16 transformations except 1. 14
Example Rename Variable Shadow Static Import Source Circle double roundpi = 3.2 double r = 1 double area() double test() 3.14 Rename refactoring Tools 3.2 Target Circle double PI = 3.2 double r = 1 double area() double test() Where import Math.PI 100/100 98/100 100 tests double area() { return PI * r * r; } 15
Generated Unit Test public void test2() { Circle var0 = new Circle(); double var1 = var0.test(); asserttrue(var1 == 3.14); } 16
Discussion It is too difficult to correctly propose all conditions in an ad-hoc way Another approach is to verify the refactoring with respect to a formal semantic This is indeed a challenge R I R R Refactoring Conditions I Implemented Conditions 17
Conclusion We presented a technique for checking refactoring safety. In specially, helping the developer to identify behavioral changes errors. 18
Limitations Behavior Only Expressed in Output A void k() B void k() void m() void k() { System.out.print( 23 ); } void k() { System.out.print( 42 ); } C void test() The current technique does not generate a test that detects this type of change 19
Generating Unit Tests for Checking Refactoring Safety Gustavo Soares, Rohit Gheyi, Tiago Massoni Márcio Cornélio, Diego Cavalcanti UFCG / UPE {gsoares, rohit, massoni, diegot}@dsc.ufcg.edu.br marcio@dsc.upe.br 20