Gradle でテストを並列実行してみる

Gradle の Java プラグインには テストを並列で実行するための機能が標準で用意されています。
通常は テスト用のプロセスは 1つしか立ち上がりませんが、

test.maxParallelForks = 5
のように設定すれば 最大 5プロセスで並列実行できるようになります。
もちろん、最近、お気に入りの Spock でも ちゃんと並列処理できます。

並列処理は クラス単位で行われるため 時間のかかる (しかも、CPU時間の少ない) メソッドが多い場合は リファクタリングしてクラスを分けた方がよいです。
内部クラスでも それぞれ ちゃんと並列処理してくれるので、ファイルはそのままで クラスだけ分けることもできます。

例えば...

class HelloSpock extends spock.lang.Specification {
    def "30秒後に目が覚めて挨拶する"() {
        Hello hello = new Hello("FOO");
        hello.sleep(30)
        expect: hello.greeting() == "Hello, FOO."
    }

    def "30秒後に目が覚めて挨拶する"() {
        Hello hello = new Hello("BAR");
        hello.sleep(30)
        expect: hello.greeting() == "Hello, BAR."
    }

    def "30秒後に目が覚めて挨拶する"() {
        Hello hello = new Hello("HOGE");
        hello.sleep(30)
        expect: hello.greeting() == "Hello, HOGE."
    }
}
のように一つのクラスに 30 秒ずつかかるメソッドがある場合、いくら並列処理するように設定しても 一つのプロセスで処理するので 90 秒かかりますが、
class HelloFooSpock extends spock.lang.Specification {
    def "30秒後に目が覚めて挨拶する"() {
        Hello hello = new Hello("FOO");
        hello.sleep(30)
        expect: hello.greeting() == "Hello, FOO."
    }
}

class HelloBarSpock extends spock.lang.Specification {
    def "30秒後に目が覚めて挨拶する"() {
        Hello hello = new Hello("BAR");
        hello.sleep(30)
        expect: hello.greeting() == "Hello, BAR."
    }
}

class HelloHogeSpock extends spock.lang.Specification {
    def "30秒後に目が覚めて挨拶する"() {
        Hello hello = new Hello("HOGE");
        hello.sleep(30)
        expect: hello.greeting() == "Hello, HOGE."
    }
}
のように内部クラスで分離すれば、3プロセスで処理されるので、30 秒 + α で実行できます。

あと、

test.forkEvery = 3
のように設定すると 一定数 テストクラスを実行したらプロセスを再起動することもできます。
上記の場合だと 同じプロセスで 3つの テストクラスを実行したら再起動されます。