ふだん使いのPCで始めるJUnitテストの分散実行

エンタープライズの現場でJUnitテストを書きましょうとプロジェクトを進めてみると、大量のテストコードが出来上がって、CIのジョブが1時間ちかくかかるようになってしまった、なんてことを聞いたことがあります。
これらを速くしようとテストコードをチューニングしたり、ジョブを分けてスレーブで実行しようとしたりするのはわりと骨の折れることです。またスレーブマシンもたくさん用意しなくてはならず、受託開発においてはそんな予算は無いことが多いので、`-Dmaven.test.skip=true`というクスリに手を染めてしまうプロジェクトもあるようです。

そんなプロジェクト向けに、準備が非常に簡単で安価に分散実行できてしまう[TestStreamer](https://github.com/kawasima/test-streamer)なるものを開発しました。

といっても作ったのはわりと昔です。
http://www.slideshare.net/kawasima/test-streamer

以前は、クライアントをAppletで作っていたのですが、このご時世厳しくなってきたので、JavaFXで作り直した次第です。

## 特長

TestStreamerはクライアント/サーバ型で動作します。

![image](https://qiita-image-store.s3.amazonaws.com/0/8475/9a712b70-7084-3e22-3d62-c83097849f90.png)

テストを実行するクライアントマシンが、ふだん使いのみんなのPCであるところが最大の特長です。また、そういうふだん使いのPCがクライアントのため、テスト対象やテストコードを事前にインストールすることは困難です。そのため[WebSocketClassLoader](https://github.com/kawasima/websocket-classloader)という、JavaのクラスローディングをWebSocketでおこなう仕組みを開発し、事前にデプロイするのではなくオンデマンドで必要なクラスのみロードするようにしています。

## 使ってみる

### TestStreamerサーバの起動

サーバには以下のようなWebコンソールが付きます。
![image](https://qiita-image-store.s3.amazonaws.com/0/8475/34b6d4af-3685-91a8-fd9a-53390ce7e194.png)

### TestStreamerクライアントのセットアップ

クライアントマシンには、ロゴ横の「client」リンクを押して、そこから以下の2通りのどちらかでクライアントアプリを動かします。

1. TestStreamerサーバからjarをダウンロードして実行する
2. TestStreamerサーバからJNLPをダウンロードしてWeb Startとして実行する

2の場合は、クライアントのjarファイルに署名が必要となるので、今のご時世、現実的には1の方法かもしれません。

クライアントを起動すると、以下のようなウィンドウが立ち上がり、自動的にTestStreamerサーバに接続されます。クライアントのセットアップはこれだけです。

![image](https://qiita-image-store.s3.amazonaws.com/0/8475/4604cd8a-d109-1788-0754-08460e108036.png)

## テストを実行する

このTestStreamerでの分散テスト実行するための環境設定も簡単です。Maven標準のテストプラグインであるsurefireからの切り替えを例にとって示します。

pom.xmlに以下のようなプロファイルを足すだけです。あとはMaven実行時に `-P test-streamer`を付けてあげれば、surefireで実行されていたものがTestStreamerで分散実行されるようになります。

```xml
<profile>
  <id>test-streamer</id>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <skipTests>true</skipTests>
        </configuration>
      </plugin>
      <plugin>
        <groupId>net.unit8.teststreamer</groupId>
        <artifactId>test-streamer-maven-plugin</artifactId>
        <version>0.1.0</version>
        <configuration>
          <testStreamerUrl>http://test-streamer.local:5000</testStreamerUrl>
        </configuration>
        <executions>
          <execution>
            <goals><goal>submit</goal></goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</profile>
```

そうすると、Webコンソール上で、実行中の状態も見ることができるようになります。
![範囲を選択_102.png](https://qiita-image-store.s3.amazonaws.com/0/8475/0ace89c8-c6e5-4686-6625-1dd784d5b9b1.png)


クライアントには順次テスト実行リクエストが飛んできて、１つずつ処理されていきます。
![範囲を選択_103.png](https://qiita-image-store.s3.amazonaws.com/0/8475/2f5c5dfb-1e03-788f-9be8-3bd1f6aba3ef.png)

テスト実行結果もWebコンソールで見ることができます。

|テストケース別の結果|Failしたテストのスタックトレース|
|:-----|:-----|
|![image](https://qiita-image-store.s3.amazonaws.com/0/8475/3aa40275-a7bf-d8b4-43b1-44cb6dce17bf.png)|![image](https://qiita-image-store.s3.amazonaws.com/0/8475/0f198b8c-da3a-1c6d-19ff-d775b14bf12f.png)|

maven実行結果も、surefireと同じように返ります。

![image](https://qiita-image-store.s3.amazonaws.com/0/8475/b6a731cb-bf69-532d-72c1-e3339d0ee2f1.png)



## まとめ

分散実行となると、すぐにクラウドに頭がとびがちですが、オフィス内にCPUパワーが有り余っている大企業は多いのではないでしょうか。TestStreamerはそういうマシンを有効活用して、簡単にテストを分散実行できます。
同じような境遇の方は、試してみていただけると幸いです。