Javaのリファクタリングした際にclassファイルの差分比較をしてテスト要否を判断したい

# Javaのリファクタリングした際にclassファイルの差分比較をしてテスト要否を判断したい
[20 万行超のコードベースをテストせずにリファクタリングリリースした話](https://tech-blog.monotaro.com/entry/2018/09/26/142451)
こちらの記事を読んだあと「Javaならclassファイルで同じことができないかな？」と思い調査しました。

調べてみた経緯としては私自身が仕事でJavaを扱っており
「リファクタリングはしたいが工数はなるべく減らしたい」という想いがあったからです。


## 調査手順
基準となるソースコードをもとに各種の変更を加えてコンパイルされたclassファイルのハッシュ値（SHA1）を比較していきます。
ハッシュ値の取得には`certutil -hashfile`コマンドを利用しました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/112941/943d6c98-8759-85db-34a6-48a6ac06dc88.png)

### 基準となるソースコード
``` Main.java
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」と出来たら嬉しいなと思いました。


## 調査内容
### コードを追記
``` Main.java
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順を変更

``` Main.java
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`

### コメントを追記（既存の行）
``` Main.java
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`

### コメントを追記（新規の行）
``` Main.java
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`

### 空行を追加
``` Main.java
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`

### インデントを変更
``` Main.java
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
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`