Javaのリファクタリングした際にclassファイルの差分比較をしてテスト要否を判断したい
20 万行超のコードベースをテストせずにリファクタリングリリースした話
こちらの記事を読んだあと「Javaならclassファイルで同じことができないかな?」と思い調査しました。
調べてみた経緯としては私自身が仕事でJavaを扱っており
「リファクタリングはしたいが工数はなるべく減らしたい」という想いがあったからです。
調査手順
基準となるソースコードをもとに各種の変更を加えてコンパイルされたclassファイルのハッシュ値(SHA1)を比較していきます。
ハッシュ値の取得にはcertutil -hashfile
コマンドを利用しました。
基準となるソースコード
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test");
}
/**
* main
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list);
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):b38492ff5641fa0f074a82ca5f397c7ba7f3575d
Main.javaからコンパイルされたMain.classファイルのハッシュ値は上記の通りです。
これと各種変更後のファイルの差分を比較します。
調査結果まとめ
調査内容が長いので結果と結論から書きます。
classファイルのハッシュ値(SHA1)に差分があったもの
- コードを追記
- コメントを追記(新規の行)
- 空行を追加
classファイルのハッシュ値(SHA1)に差分がなかったもの
- import順を変更
- コメントを追記(既存の行)
- インデントを変更
- グループ化の括弧を変更する
結論
classファイルのハッシュ値(SHA1)に差分がなかったものの変更に関しては、classファイルの差分比較して「テストなしでOK」と言えそうですね。
特にインデントの変更はソースコード上で大量の差分になりやすいので「classファイルを比較して差分なしだからOK」と出来たら嬉しいなと思いました。
調査内容
コードを追記
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test"); System.out.println("test2");
}
/**
* main
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list);
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):2356a12ac1ca0147356c1eb9824bdacf94e5eaac
import順を変更
import java.util.List;
import java.util.Arrays;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test");
}
/**
* main
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list);
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):b38492ff5641fa0f074a82ca5f397c7ba7f3575d
コメントを追記(既存の行)
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test");
}
/**
* main addcomment
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list);
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):b38492ff5641fa0f074a82ca5f397c7ba7f3575d
コメントを追記(新規の行)
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test");
}
/**
* main
* add comment
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list);
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):a05020054dd7c85ef01c20bc9d1f0cc45c46d1e1
空行を追加
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test");
}
/**
* main
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list);
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):a05020054dd7c85ef01c20bc9d1f0cc45c46d1e1
インデントを変更
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test");
}
/**
* main
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list);
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):b38492ff5641fa0f074a82ca5f397c7ba7f3575d
グループ化の括弧を変更する
import java.util.Arrays;
import java.util.List;
public class Main {
/**
* test
*/
public static void test() {
System.out.println("test");
}
/**
* main
* @param args
*/
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
System.out.println((list));
System.out.println("main");
test();
}
}
ハッシュ値(SHA1):b38492ff5641fa0f074a82ca5f397c7ba7f3575d